3

使用虛擬串列阜VCP

3.1 虛擬串列阜VCP簡介

SIOC與電腦溝通的介面有兩種,一是UART傳輸介面;二是USB傳輸介面。而Virtual COM Port(VCP)就由一個驅動程式,將實體的USB傳輸介面模擬成COM Port傳輸介面,由於並非真正的COM Port,故稱Virtual COM Port。簡單來說,Virtual COM Port就是USBRS232的介面。

image001  

圖一:USBRS232的介面

一般Virtual COM PortIO有兩組,SIOC也不例外,在SIOC中,一為VCP-to-PC,二為VCP-to-device,示意圖如下:

image002  

 

Virtual COM Port的兩端,各有專屬的buffer在接收資料,分別為USB_Rx_BufferUSART_Rx_Buffer,分別處理VCP-to-PC介面與VCP-to-device介面的資料。

 

3.2  VCP驅動程式安裝和設定

 

電腦作業系統若是為XP,第一次連接STM Virtual COM Port會無法成功安裝驅動程式,至時可手動到裝置管理員找到STM Virtual COM Port,選擇更新驅動程式,就可指定驅動程式位置(stmcdc.inf)。作業系統若為WIN7,其驅動程式的安裝步驟與XP無異。

image003  

 

電腦與SIOC溝通的軟體,我們以超級終端機與putty為主要介面,期中這裡有些設定是我們需要注意的,以下為超級終端機的設定:

image004    

image005  

 

 

 

 

以下是putty的設定,因為某些WIN7的使用者,其系統並沒有超級終端程式,為此我們也介紹putty的設定原則:

image006  

image007  

 

做足這些準備,就可以開始與SIOC溝通了!

 

 

 

3.3  電腦與SIOC實驗板的通訊

 

在描述如何使用scanf()printf()之前,我們先了解SIOC它底下的IO運作方式,再依序將讀者帶入使用scanf()printf(),方能更加了解SIOC溝通方式

 

l   存取陣列資料

 

首先是VirtualCOMPort to PC的運作:

image008  

 

在範例程式當中,點選hw_config.c檔找到以下程式碼:

 

void VCP_To_USB(uint8_t * buffer, int  length)

 

 

int cnt;

 

for(cnt=0;cnt<length;cnt++){

 

                if (linecoding.datatype == 7){ /* datatype7bits的資料格式*/

 

                        USART_Rx_Buffer[USART_Rx_ptr_in] = buffer[cnt]& 0x7F;

 

                } 

 

                else if (linecoding.datatype == 8)  { /* datatype8bits的資料格式*/

 

               USART_Rx_Buffer[USART_Rx_ptr_in] = buffer[cnt];

 

                }

 

                USART_Rx_ptr_in++;

 

                /* To avoid buffer overflow */

 

                if(USART_Rx_ptr_in == USART_RX_DATA_SIZE){

 

                        USART_Rx_ptr_in = 0;

 

                }

 

        }

 

}

 

USART_Rx_Buffer為一個專屬處理VCP_To_USB方向的資料流的BUFFER,將我們要顯示在超級終端機上的資訊,放入USART_Rx_Buffer中,Virtual COM Port會自動的將資料轉送到PC上。故此,我們只須在main.c中呼叫VCP_To_USB()函式即可。範例如下:

 

uint8_t Buffer [50]={1,2,3,4,5};

 

length = strlen(buffer); /*擷取字串長度*/

 

        VCP_To_USB(buffer, length);

 

 

 

接下來我們介紹PC to VirtualCOMPort的運作:

image009  

 

在範例程式當中,點選usb_endp.c檔找到以下程式碼:

 

void EP3_OUT_Callback(void)

 

{

 

  uint16_t USB_Rx_Cnt;

 

  /* Get the received data buffer and update the counter */

 

  USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, USB_Rx_Buffer);

 

  /* USB data will be immediately processed, this allow next USB traffic beeing 

 

  NAKed till the end of the USART Xfet */

 

  USB_To_USART_Send_Data(USB_Rx_Buffer, USB_Rx_Cnt);

 

 }

 

此段程式碼負責處理來自PC端超級終端機的訊息,程式將data放入USB_Rx_Buffer,並用USB_Rx_Cnt計算資料筆數。故在main.c當中,我們可以用直接讀取USB_Rx_Buffer的方式收取資料。範例如下:

 

uint8_t data_buffer [80];

 

        uint8_t index = 0;

 

        while(1){

 

                while(USB_Rx_Cnt==0){}   /*USB_Rx_Buffer 為空*/

 

for(CHAR_Rx_Cnt; CHAR_Rx_Cnt<USB_Rx_Cnt; CHAR_Rx_Cnt++, index++){

 

                               buffer[index] = USB_Rx_Buffer[CHAR_Rx_Cnt];

 

                        }

 

                        USB_Rx_Cnt = 0;

 

                }

 

                index = 0;

 

l   使用scanf()和printf()

 

我們用浯陽科技開發的library,將標準函式庫stdio.h裡的printf()scanf()導向Virtual COM Port的方式實現I/O控制。

 

 

 

l    立即演練

 

實驗1  “Hello SIOC!”

 

實驗說明:請用printf()在超級終端機持續印出”Hello, SIOC”,並且使用Delay()函式製造間隔時間

 

SIOC…

 

實驗2  使用超級終端機的SIOC輸入輸出

 

實驗說明:設計一個簡易程式讓使用者輸入兩個數值,然後輸出運算結果。

 

   

 

 

 

Type

Qualifying Input

Type of argument

c

Single character

char *

d

Decimal integer

int *

e,E,f,g,G

Floating point

float *

o

Octal integer

int *

s

String of characters.

char *

u

Unsigned decimal integer.

unsigned int *

x,X

Hexadecimal integer.

int *

 

 

 

 

  

當程式燒錄進SIOC連接Virtual COM Port後,程式第一行Printf()內的字串是否沒有顯示出來?這是為什麼?又要如何解決呢?

這是因為當使用這燒完程式,離開DFU模式後,SIOC就立刻轉換成Virtual COM Port,此時程式就已經開始執行,但是使用者卻尚未將SIOC與超級終端機或putty連接上,以至於沒有收到程式第一行Printf()的字串內容。

解決方法就是使用getchar()函式,getchar()可讓程式強迫等待來自鍵盤上的字元輸入,藉此方法可讓程式等待在getchar(),不至於在連接超級終端機或putty前,程式就已先偷跑在前,讓使用者漏掉訊息。示意如下:

#include  "stdio.h "

int main(void)

{

char a[80];

getchar();  /*強迫程式等待任意字元輸入*/

printf("enter number.");

scanf("%s",&a);

printf("%s \n",a);

}

這是在程式撰寫上的一個小技巧,另外還有使用scanf來讀字串,字串中不能有空白,若有空白會被當成兩個不同的字串,請特別注意這個小細節。

實驗3  計算BMI

實驗說明:在超級終端機可以輸入姓名、身高、體重,並顯示計算姓名與診斷結果。BMI公式:BMI = 體重(kg) / 身高(m) 2

成人的體重分級與標準

成人的體重分級與標準

分    級

身體質量指數

分    級

體重過輕

BMI < 18.5

體重過輕

正常範圍

18.5  BMI <24

正常範圍

過    重

24  BMI

過    重

l    綜合實驗

設計一個程式,要求使用者輸入身分證字號,並驗證該身分證字號是否正確。這裡我們以A123456789為例子。

此實驗的第一個步驟:先把身分證字號格式化,示意如下:

A

1

2

3

4

5

6

7

8

9

X1

X2

D1

D2

D3

D4

D5

D6

D7

D8

D9

                     

接著看下列表格:

A

B

C

D

E

F

G

H

J

10

11

12

13

14

15

16

17

18

K

L

M

N

P

Q

R

S

T

19

20

21

22

23

24

25

26

27

U

V

X

Y

W

Z

I

O

 

28

29

30

31

32

33

34

35

 

將第一個英文字母,依據上面表格,拆成兩個數字,分別填到X1與 X2中。

1

0

1

2

3

4

5

6

7

8

9

X1

X2

D1

D2

D3

D4

D5

D6

D7

D8

D9

利用公式將數字加總:Y=X1 + X2*9 + D1*8 + D2*7 + D3*6 + D4*5 + D5*4 + D6*3 + D7*2 + D8*1 + D9*1

Y若能夠被10整除,則為正確之身份証號碼。

另外還有性別辨識碼,字串長度等都可以列入辨別身分證字號是否合法的判斷條件,在程式設計當中可以將條件加入進去。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 youboook 的頭像
    youboook

    youboook的部落格

    youboook 發表在 痞客邦 留言(0) 人氣()