1.1 整體框架介紹
本次提供以下模塊的Demo程序:

圖1-1
整個工程包含3個文件夾,如下所示:

Source包含.c文件,如下所示:

每個模塊包含兩個.c文件,一個命名為xxx..c,一個命名為xxx_Test.c;第一個c文件包含了模塊相關的配置程序,第二個c文件包含了模塊相關的測試程序;
Include中存放各個模塊的頭文件及系統頭文件。
1.2使用實例說明
在Keil中選擇包含相應模塊程序的工程序進行編譯加載,對于有些模塊,因為具有多個工作方式,為了測試不同工作方式下的功能,可在相應模塊的.h文件中打開相應的宏定義,再進行編譯加載;例如,需要測試Timer2工作在方式0捕捉模式的功能,可按如下步驟進行測試:
- 在工程下拉菜單中選擇Timer2工程(如圖1-2所示);

圖1-2
選擇之后,包含Timer2模塊程序的工程被打開,如下圖所示:

圖1-3
.c文件中帶“”,表示該文件包含在當前工程中,否則不包含在當前工程中。
- 在相應的Timer.h頭文件中打開宏定義“#define MODE0”(如圖1-4所示);

圖1-4
2.1.1工作方式配置介紹
系統時鐘可配置為低頻、高頻,PLL高頻3種模式,sysclk_define.h文件包含以下幾個宏定義,分別用于初始化時鐘在相應的模式:
#define LOW_FREQUENCE:執行函數void SetClk()可將系統時鐘配置為低頻模式; #define HIGH_FREQUENCE:執行函數void SetClk()可將系統時鐘配置為高頻模式; #define PLL_HIGH_FREQUENCE:執行函數void SetClk()可將系統時鐘配置為高頻
PLL模式;
將相應功能的宏定義打開,屏蔽其他宏定義,編譯、加載運行可進行測試。
2.1.2測試程序介紹
選擇“Sysclk”工程,打開宏定義“#define LOW_FREQUENCE”,其它宏定義都屏蔽,設置系統時鐘為低頻時鐘,Option中選擇內建128KHz RC振蕩時鐘作為OSC1CLK;編譯、加載運行,測試P0.0口可得到以下9.1KHz波形:

圖2-1
由于c程序中IO翻轉一次需要7個時鐘周期,所以IO翻轉產生的方波頻率應為:
f=128KHz/(7*2)=9.1KHz
注:如果不能觀察到上述結果,則檢查option是否配置正確;
2.1.3寄存器簡要介紹
CLKCON
| | |
| 32K_SPDUP | 32.768KHz振蕩器加速模式控制位 0:32.768kHz振蕩器常規模式, 由軟件清除 1:32.768kHz加速模式,由軟件或者硬件置起 詳細說明見Spec |
| | 系統時鐘預分頻器 00:fSYS = fOSC 01:fSYS = fOSC / 2 10:fSYS = fOSC / 4 11:fSYS = fOSC / 12 如果選擇OSC1CLK為SYSCLK時鐘源,則fSYS = fOSC1,與CLKS[1:0]內容無關。 |
| | OSC2CLK開關控制寄存器 0:關閉OSC2CLK 1:打開OSC2CLK |
| | 頻率選擇位 0:選擇OSC1CLK為SYSCLK 1:選擇OSCSCLK為SYSCLK |
PLLCON
| | |
| | PLL狀態位 0:鎖相環沒有鎖住相位 1:鎖相環鎖住相位 鎖相環鎖住相位后可以輸出穩定的時鐘 |
| | PLL開關控制位 0:PLL關閉 1:PLL開啟 PLL開啟必須OSC2ON=1時才有效 |
| | PLL系統時鐘源控制位 0:PLL不作為OSCSCLK 1:PLL的二分頻作為OSCSCLK PLL的輸入時鐘必須大于5M |
相關內部RC校正寄存器CLKLO、CLKRC0、CLKRC1的詳細說明見Spec。
SH88F6161提供61個位可編程雙向I/O端口,端口數據在寄存器Px中,端口控制寄存器PxCRy控制端口是作為輸入或者輸出。當端口作為輸入時,每個I/O端口帶有由PxPCRy控制的內部上拉電阻。
demo程序中函數void Sysclk_Test(),以IO翻轉為例給出了IO的配置使用方法;
SH88F6161有定時器2和定時器3兩個定時器,定時器2可配置為16位捕獲、16位自動重載、可編程時鐘輸出三種方式;定時器3只可配置為16位自動重載方式。
demo程序以Timer2為例給出了不同工作模式的配置方法。
2.3.1工作方式配置介紹
timer_define.h文件中包含以下幾個宏:
#define MODE0:設置Timer2工作在16位捕獲方式(下降沿捕獲)
#define MODE1:設置Timer2工作在16位重載方式
#define MODE2:設置Timer2工作在可編程時鐘輸出方式
將相應功能的宏定義打開,屏蔽其他宏定義,編譯、加載運行可進行測試。
2.3.2測試程序介紹
選擇“Timer2”工程,依次在timer_define.h文件中打開相應宏,然后進行編譯加載全速運行,觀察現象
- 當打開宏“#define MODE0”,全速運行后,T2EX引腳輸入下降沿會產生一次捕獲,并產生外部事件捕獲中斷;
- 當打開宏“#define MODE1”,全速運行后,定時器工作在16位自動重載方式,定時產生溢出中斷;
- 當打開宏“#define MODE2”,全速運行后,定時器工作在可編程時鐘輸出方式,產生如下31.9KHz波形(系統時鐘為128KHz);

圖2-2
輸出時鐘頻率計算公式:
、
2.3.3相關寄存器介紹
RCAP2L,RCAP2H,TL2,TH2
位編號 | 位符號 | 說明 |
7-0 | RCAP2L [7:0] | 定時器2重載/捕獲數據 |
RCAP2H [7:0] |
7-0 | TL2 [7:0] | 定時器2高位低位計數器 |
TH2 [7:0] |
T2CON
位編號 | 位符號 | 說明 |
7 | TF2 | 定時器2溢出標志位 0:無溢出(必須由軟件清0) 1:溢出(由硬件設1) |
6 | EXF2 | T2EX引腳外部事件輸入(下降沿)被檢測到的標志位 0:無外部事件輸入(必須由軟件清0) 1:檢測到外部輸入(如果EXEN2 = 1,由硬件設1) |
3 | EXEN2 | T2EX引腳上的外部事件輸入(下降沿)用作重載/捕獲觸發器允許/禁止控制位 0:忽略T2EX引腳上的事件 1:檢測到T2EX 引腳上一個下降沿,產生一個捕獲或重載 |
2 | TR2 | 定時器2開始/停止控制位 0:停止定時器2 1:開始定時器2 |
1 | C/ | 定時器2定時器/計數器方式選定位 0:定時器方式,T2引腳用作I/O端口 1:計數器方式,內部上拉電阻被打開 |
0 | CP/ | 捕獲/重載方式選定位 0:16位帶重載功能的定時器/計數器 1:16位帶捕獲功能的定時器/計數器 |
T2MOD
位編號 | 位符號 | 說明 |
7 | TCLKP2 | 分頻選擇控制位 0:選擇系統時鐘的1/12作為定時器2的時鐘源 1:系統時鐘作為定時器2的時鐘源 |
1 | T2OE | 定時器2輸出允許位 0:設置P2.4/T2作為時鐘輸入或I/O端口 1:設置P2.4/T2作為時鐘輸出 |
0 | DCEN | 遞減計數允許位 0:禁止定時器2作為遞增/遞減計數器,定時器2僅作為遞增計數器 1:允許定時器2作為遞增/遞減計數器 |
SH88F6161具有四個可編程計數器,分別為PCA0、PCA1、PCA2、PCA3;
demo程序以PCA0為例,給出了其比較/捕捉模塊分別工作于Mode0~Mode3時的參考程序。
2.4.1工作方式配置介紹
pca_define.h文件中包含以下幾個宏:
#define MODE0:配置比較/捕捉模塊0工作在邊沿觸發模式
#define MODE1:配置比較/捕捉模塊0工作在軟件定時方式
#define MODE2: 配置比較/捕捉模塊0工作在頻率輸出方式
#define MODE3_PWM8:配置比較/捕捉模塊0工作在8位脈寬調制
#define MODE3_PWM16:配置比較/捕捉模塊0工作在16位脈寬調制
#define MODE3_XPWM16:配置比較/捕捉模塊0工作在16位相位修正脈寬調制
#define MODE3_XPPWM16:配置比較/捕捉模塊0工作在16位相頻修正脈寬調制
將相應功能的宏定義打開,屏蔽其他宏定義,編譯、加載運行可進行測試。
2.4.2測試程序介紹
選擇“PCA”工程,依次在pca_define.h文件中打開相應宏,然后進行編譯加載全速運行,觀察現象;
1. 打開宏“#define MODE0”,屏蔽其他宏定義,編譯加載后,全速運行,P0CEX0引腳上升沿/下降沿會觸發一次捕捉,并產生相應中斷;
2. 打開宏“#define MODE1”,屏蔽其他宏定義,編譯加載后,全速運行,可以實現連續軟件定時,當PCA0計數值與P0CPH0和P0CPL0中的值匹配時產生一次中斷,同時P0CEX0口翻轉一次;(PxTOP,PxCPn可變)
3. 打開宏“#define MODE2”,屏蔽其他宏定義,編譯加載后,全速運行,P0CEX0引腳可輸出如下波形(3.965KHz):

圖2-3
FPxCEXn= FPCAx /(2 × PxCPHn)
如果應用中需要改變波形占空比和頻率,則可通過適時地改變PxCPHn來獲得相應的波形;PxTOPL固定為0xFF,用戶可以配置PxTOPH來改變計數最大值;
4. 打開宏“#define MODE3_PWM8”,屏蔽其他宏定義,編譯加載后,全速運行,P0CEX0輸出占空比為0.8的正向波形,P0CEX1輸出占空比為0.8的反向波形,如下圖所示:

圖2-4
Duty=(256-(PxCPHn+1))/256
如果應用中需要Duty可變的PWM波形,則可通過適時的改變PxCPHn來獲取希望波形;
PxTOPL不可改變;
5. 打開宏“#define MODE3_PWM16”,屏蔽其他宏定義,編譯加載后,全速運行,P0CEX0輸出占空比為0.8的正向波形,P0CEX1輸出占空比為0.8的反向波形,如下圖所示:

圖2-5
Duty=(65536-(PxCPn+1))/65536
如果應用中需要Duty可變的PWM波形,則可通過適時的改變PxCPn(PxCPHn,PxCPLn)和PxTOP來獲取希望波形;
6. 打開宏“#define MODE3_XPWM16”,屏蔽其他宏定義,編譯加載后,全速運行,P0CEX0輸出頻率為250Hz的正向波形,P0CEX1輸出頻率為250Hz的反向波形,如下圖所示:

圖2-6
如果應用中需要頻率和占空比可變的波形,則可通過適時的改變PxTOP和PxCPn(PxCPHn,PxCPLn)來獲取相應波形;在一個定時器時鐘周期里PCAx值等于PxTOP值,然后在下一次計數到來時PxTOP和PxCPn將得到更新。
7. 打開宏“#define MODE3_XPPWM16”,屏蔽其他宏定義,編譯加載后,全速運行,P0CEX0輸出頻率為250Hz的正向波形,P0CEX1輸出頻率為250Hz的反向波形,如下圖所示:

圖2-7
如果應用中需要頻率和占空比可變的波形,則可通過適時的改變PxTOP和PxCPn(PxCPHn,PxCPLn)來獲取相應波形;PxCPn和PxTOP在0x0000點更新。
注:對于XPWM和XPPWM工作方式,一定要配置相應的PCAx工作在雙沿模式,否則相應口將不能正常輸出波形;
Demo程序給出了LCD的使用實例,以4COM,2SEG為例,用戶可根據實際需要選擇合適COM數和SEG數做相應的IO配置;配置參考void init_lcd()。
選擇“Lcd”工程,編譯加載運行,觀察SEG1、SEG2、COM1~COM4口波形;
Demo程序給出了LED的使用實例,以2COM,8SEG為例,用戶可根據實際需要選擇合適COM數和SEG數做相應的IO配置;配置參考void init_led()。
選擇“Led”工程,編譯加載運行,觀察COM1、COM2、SEG1~ SEG8口波形;
2.5.1寄存器簡要介紹
DISPCON
位編號 | 位符號 | 說明 |
7 | DISPSEL | LCD,LED選擇控制位 0:選擇LCD驅動器,LED驅動器無效 1:選擇LED驅動器,LCD驅動器無效 |
6 | DISPON | LCD使能控制位 0:禁止LCD驅動器 1:允許LCD驅動器 |
5-4 | DUTY[1:0] | LCD占空比選擇位 00:1/4占空比,1/3偏置 01:1/5占空比,1/3偏置 1X:1/6占空比,1/3偏置 |
3-0 | VOL[3:0] | LCD對比度控制位 0000:VLCD = 0.531VDD 0001:VLCD = 0.563VDD 0010:VLCD = 0.594VDD 0011:VLCD = 0.625VDD 0100:VLCD = 0.656VDD 0101:VLCD = 0.688VDD 0110:VLCD = 0.719VDD 0111:VLCD = 0.750VDD 1000:VLCD = 0.781VDD 1001:VLCD = 0.813VDD 1010:VLCD = 0.844VDD 1011:VLCD = 0.875VDD 1100:VLCD = 0.906VDD 1101:VLCD = 0.938VDD 1110:VLCD = 0.969VDD 1111:VLCD = 1.000VDD |
DISPCON1
位編號 | 位符號 | 說明 |
4 | RLCD | LCD偏置電阻選擇控制位 0:LCD偏置電阻為225k 1:LCD偏置電阻總和為900k |
3-2 | FCCTL[1:0] | 充電時間控制位 00:1/8 LCD com周期 01:1/16 LCD com周期 10:1/32 LCD com周期 11:1/64 LCD com周期 充電時間控制位僅在快速充電模式下有效 |
1-0 | MOD[1:0] | 驅動模式選擇位 00:傳統電阻型模式,偏置電阻總和為225k/900k 01:傳統電阻型模式,偏置電阻總和為60k 1X:快速充電模式,偏置電阻總和自動在60k和225k/900k之間切換 |
其它相關寄存器詳見Spec。
TWI串行總線采用兩根線(SDA和SCL)在總線和裝置之間傳遞信息。SH88F6161完全符合TWI總線規范,自動對字節進行傳輸進行處理,并對串行通訊進行跟蹤。
2.6.1工作方式配置介紹
twi_define.h文件中定義了以下幾個模式:
#define MT_MODE:打開該宏,配置6161工作在主機傳送模式;
#define MR_MODE:打開該宏,配置6161工作在主機接收模式;
#defineSLAVE_MODE:打開該宏,配置6161工作在從機模式;
將相應功能的宏定義打開,屏蔽其他宏定義,編譯、加載運行可進行測試。
2.6.2測試程序介紹
Twi_Test.c分別以作為主機和從機傳送和接收10個byte數據為例給出了該模塊的應用;
1. 選擇“Twi”工程后,打開宏定義“MT_MODE”,編譯、加載運行可測試6161作為主機向從機傳送數據,分別為“0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A……..”
2. 選擇“Twi”工程后,打開宏定義“MR_MODE”,編譯、加載運行可測試6161作為主機從從機接收10個byte數據;
3. 選擇“Twi”工程后,打開宏定義“SLAVE_MODE”,編譯、加載運行可測試6161作為從機:
- 向主機發送10個byte數據,分別為“0x40, 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49”
- 從主機接收10個byte數據,分別為“0x40, 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49”
本模塊測試需要兩個6161板子,一個作為主機,一個作為從機進行配合。
注:如果不能得到正確結果,請檢查SCL和SDA是否接上拉電阻,通常選擇10k
串行外部設備接口(SPI)是一種高速串行通信接口,允許MCU與外圍設備(包括其它MCU)進行全雙工,同步串行通訊。
2.7.1工作方式配置介紹
spi_define.h文件中定義了以下兩個模式:
#define SLAVE_MODE:打開該宏,配置6161作為從機;
#define MASTER_MODE:打開該宏,配置6161作為主機;
2.7.2測試程序介紹
以6161作為主機向另一塊作為從機的6161傳送數據為例,具體過程如下:
主機6161向從機6161傳送“0x40, 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A”;從機收到主機發送的數據后,將相應數據返回給主機,主機接收到從機返回的數據后,將其保存到rcv_data[]數組中。
選在“Spi”工程后,打開宏定義“#define MASTER_MODE”編譯,下載運行使其作為主機;
選在“Spi”工程后,打開宏定義“#define SLAVE_MODE”編譯,下載運行使其作為從機;
本模塊程序運行測試需要兩塊6161板子配合。
注:如果從機向主機返回的數據內容與期望值有差別,可嘗試提高從機的的系統時鐘頻率,或降低主機的系統時鐘頻率;
本次實例中,以一個主設備一個從設備的通訊網絡為例,因此無需控制SS引腳,即只需接SCK,MOSI,MISO三根信號線;
2.7.3寄存器簡要介紹
SPCON
| | |
| | 傳送方向選擇位 0:MSB優先發送 1:LSB優先發送 |
| | SP設備選擇位 0:配置SPI作為從屬設備 1:配置SPI作為主設備 |
| | 時鐘相位控制位 0:SCK周期的第一沿采集數據 1:SCK周期的第二沿采集數據 |
| | 時鐘極性控制位 0:在Idle狀態下SCK處于低電平 1:在Idle狀態下SCK處于高電平 |
| | 引腳控制位 0:在主和從屬模式下,打開引腳 1:在主和從屬模式下,關閉引腳 如果SSDIS置1,不產生MODF中斷請求。 在從屬模式下,如果CPHA = 0,該位不起作用。 |
| | 串行外部設備時鐘速率選擇位 000: fSYS /2 001: fSYS /4 010: fSYS /8 011: fSYS /16 100: fSYS /32 101: fSYS /64 110: fSYS /128 111: fSYS /256 |
SPSTA
| | |
| | |
| | 串行外部設備數據傳送標志位 0:由軟件清0 1:表明已完成數據傳輸,由硬件置1 |
| | 模式故障位 0:由軟件清0 1:表明引腳電平與SPI模式不一致,由硬件置1 |
| | 寫入沖突標志位 0:有軟件清0,表明已處理寫入沖突 1:由硬件置1,表明檢測到一個沖突 |
| | 接收超限位 0:表明已處理接收超限,由軟件清0 1:表明已檢測到接收超限,由硬件置1 |
SPDAT
| | |
| | 寫入SPDAT的數據被放置到發送移位寄存器中。讀取SPDAT時將獲得接收移位換寄存器的數據。 |
Uart工作方式列表:
SM0 | | | 類型 | 波特率 | 幀長度 | 起始位 | 停止位 | 第9位 |
0 | | | 同步 | fSYS/(4或12) | 8位 | 無 | 無 | 無 |
0 | | | 異步 | 自帶波特率發生器的溢出率/16 | 10位 | 1 | 1 | 無 |
1 | | | 異步 | fSYS/(32或64) | 11位 | 1 | 1 | 0,1 |
1 | | | 異步 | 自帶波特率發生器的溢出率/16 | 11位 | 1 | 1 | 0,1 |
通過配置相應寄存器可使Uart工作在不同的工作方式,本次Demo程序以Uart0的方式1為例,給出了6161傳送數據和接收數據的實例。
注:Uart0和Uart1完全相同;
2.8.1工作方式配置介紹
uart_define.h文件中,定義了以下兩個宏:
#define Enable_uart_TX_test:測試6161工作在方式1傳送數據;
#define Enable_uart_RX_test:測試6161工作在方式1接收數據;
2.8.2測試程序介紹
本項測試需結合串口助手調試,選擇“Uart”工程后,打開宏定義“#define Enable_uart_TX_test”,編譯、加載運行后,通過串口助手可看到6161連續傳送0x96;
注:測試時,系統時鐘選擇外掛晶振8M,波特率為9600;
2.8.3寄存器介紹
PCON
位編號 | 位符號 | 說明 |
7 | SMOD | UART0/1波特率加倍器 0:在方式2中,波特率為系統時鐘的1/64 1:在方式2中,波特率為系統時鐘的1/32 |
6 | SSTAT | SCON[7:5]功能選擇 0:SCON[7:5]工作方式作為SM0,SM1,SM2 1:SCON[7:5]工作方式作為FE,RXOV,TXCOL |
3-2 | GF[1:0] | 用于軟件的通用標志位 |
1 | PD | 掉電模式控制位 |
0 | IDL | 空閑模式控制位 |
SCON
位編號 | 位符號 | 說明 |
7-6 | SM[0:1] | EUART0串行方式控制位,SSTAT = 0 00:方式0,同步方式,固定波特率 01:方式1,8位異步方式,可變波特率 10:方式2,9位異步方式,固定波特率 11:方式3,9位異步方式,可變波特率 |
7 | FE | EUART0幀出錯標志位,當FE位被讀時,SSTAT位必須被置位 0:無幀出錯,由軟件清零 1:幀出錯,由硬件置位 |
6 | RXOV | EUART0接收溢出標志位,當RXOV位被讀時,SSTAT 位必須被置位 0:無接收溢出,由軟件清零 1:接收溢出,由硬件置位 |
5 | SM2 | EUART0多處理機通訊允許位(第9位“1”校驗器),SSTAT = 0 0:在方式0下,波特率是系統時鐘的1/12 在方式1下,禁止停止位確認檢驗,任何停止位都會置位RI 在方式2和3下,任何字節都會置位RI 1:在方式0下,波特率是系統時鐘的1/4 在方式1下,允許停止位確認檢驗,只有有效的停止位(1)才能置位RI 在方式2和3下,只有地址字節(第9位 = 1)才能置位RI |
5 | TXCOL | EUART0發送沖突標志位,當TXCOL位被讀時,SSTAT位必須被置位 0:無發送沖突,由軟件清零 1:發送沖突,由硬件置位 |
4 | REN | EUART0接收器允許位 0:接收禁止 1:接收允許 |
3 | TB8 | 在EUART0的方式2和3下發送的第9位,由軟件置位或清零 |
2 | RB8 | 在EUART0的方式1,2和3下接收的第9位 在方式0下,不使用RB8 在方式1下,如果接收中斷發生,停止位移入RB8 在方式2和3下,接收第9位 |
1 | TI | EUART0的傳送中斷標志位 0:由軟件清零 1:由硬件置位 |
0 | RI | EUART0的接收中斷標志位 0:由軟件清零 1:由硬件置位 |
SBUF
位編號 | 位符號 | 說明 |
7-0 | SBUF[7:0] | 這個寄存器尋址兩個寄存器:一個移位寄存器和一個接收鎖存寄存器 SBUF的寫入將發送字節到移位寄存器中,然后開始傳輸 SBUF的讀取返回接收鎖存器中的內容 |
SADDR、SADEN(多機通訊時需設置)
位編號 | 位符號 | 說明 |
7-0 | SADDR[7:0] | 寄存器SADDR定義了EUART0的從機地址 |
7-0 | SADEN[7:0] | 寄存器SADEN是一個位屏蔽寄存器,決定SADDR的哪些位被檢驗 0:SADDR中的相應位被忽略 1:SADDR中的相應位對照接收到的地址被檢驗 |
SBRTH、SBRTL
位編號 | 位符號 | 說明 |
7 | SBRTEN | EUART0波特率發生器使能控制位 0:關閉(默認) 1:打開 |
6-0, 7-0 | SBRT[14:0] | EUART0波特率發生器計數器高7位和低8位寄存器 |
SFINE
位編號 | 位符號 | 說明 |
3-0 | SFINE[3:0] | EUART0波特率發生器微調數據寄存器 |
USB主機和從機之間的通信是建立在既定的USB協議基礎上,需要主機驅動程序和從機驅動程序配合實現;根據不同的應用場合,用戶可以編寫相應的USB驅動程序實現與PC主機的通訊。
USB協議規定了USB設備和PC主機進行通訊的過程,主機和從機進行通訊的第一個階段是枚舉過程,通過枚舉,從機設備會將其描述符信息發送給主機,主機會在枚舉完之后根據設備的描述符信息發起后續的通信,后續通信的過程根據枚舉時得到的設備配置信息的不同而不同。
2.9.1總體流程圖
使用USB模塊之前,首先需調用模塊初始化函數void usb_init (),之后USB從機將等待主機發送命令,并產生相應中斷;

圖2-8
2.9.2基本通信過程說明
如果從機可以接收主機向控制端點0發送的數據,收到SETUP命令后,需進行如下操作:
- 置位OEP0RDY;
- 待產生OEP0中斷后,通過OEP0CNT寄存器可獲取接收到的數據個數,從EP0 OUT Buf可獲取所收到的數據內容;
- 如果OEP0CNT的值小于8,則IEP0CNT清0,置位IEP0RDY,此時主機會向從機發送In包,從機將向主機傳送0長度數據包,本次控制傳輸結束。要想開始下一筆控制傳輸,主機需重新發送SETUP包;
- 如果OEP0CNT的值等于8,則重復步驟1)~3);
如果從機有數據通過端點0向主機發送,收到SETUP命令后,需執行如下操作:
- 設置相應的IEP0DTG;
- 向EP0 IN BUF填寫數據內容,向IEP0CNT填寫數據個數;
- 置位IEP0RDY;
- 待產生IEP0中斷后,如果IEP0CNT值小于8,表示從機沒有剩余數據向主機發送,此時應置位OEP0RDY,等待主機向從機傳送0長度數據包產生OEP0中斷,本次控制傳輸結束;
- 如果IEP0CNT值等于8,表示從機還有數據向主機發送,此時應重復1)~4);
如果從機可以接收主機向端點1傳送的數據,則需執行如下操作:
- 設置OEP1BUFSEL占用相應buf,
- 置位OEP1RDY;
- 待產生OEP1中斷后,通過OEP1CNT寄存器可獲取接收到的數據個數,釋放當前被占用的buf,從中可獲取接收到的數據內容,如果當前接收到的數據個數等于16,則重復1)~3);如果當前接收到的數據個數小于16,本次傳輸結束;
如果從機有數據通過端點1向主機發送,則需執行如下操作:
- 設置IEP1DTG;
- 填寫IEP1CNT,填寫相應的BUF,并設置IEP1BUFSEL占用BUF;
- 置位IEP1RDY,向主機發送數據;
- 產生IEP1中斷后,如果從機沒有數據傳送(即IEP1CNT小于16),則本次數據傳輸結束,否則重復步驟1)~4);
如果從機可以接收主機向端點2傳送的數據,則需執行如下操作:
- 設置OEP2BUFSEL占用相應buf,
- 置位OEP2RDY;
- 待產生OEP2中斷后,通過OEP2CNT寄存器可獲取接收到的數據個數,釋放當前被占用的buf,從中可獲取接收到的數據內容,如果當前接收到的數據個數等于64,則重復1)~3);如果當前接收到的數據個數小于64,本次傳輸結束;
如果從機有數據通過端點2向主機發送,則需執行如下操作:
- 設置IEP2DTG;
- 填寫IEP2CNT,填寫相應的BUF,并設置IEP2BUFSEL占用BUF;
- 置位IEP2RDY,向主機發送數據;
- 產生IEP2中斷后,如果從機沒有數據傳送(即IEP2CNT小于64),則本次數據傳輸結束,否則重復步驟1)~4);
2.9.3應用實例
本次Demo程序以HID類設備為例,給出了枚舉過程。

當6161下載該程序運行后,插入PC,PC端會識別到一個HID類設備插入,如下所示:

如果用戶需要實現其他應用,則應根據USB協議規定修改相應的描述符信息,并增加相應的類請求響應程序以及后續通信相關程序。
ADC負責模擬信號到相應12位的數字信號的轉換,支持VDD,內建1.5V,內建2.5V,外接VREF四種基準電壓,可通過軟件啟動AD轉換,也可通過觸發源觸發AD轉換,另外通過啟動比較功能,可實現連續轉換。
2.10.1工作方式配置介紹
adc_define.h文件中定義了以下幾個宏:
#define STARTUP_BY_SOFTWARE:打開該宏,測試軟件觸發一次ADC0轉換
#define STARTUP_BY_HARDWARE:打開該宏,測試外部中斷2上升沿觸發ADC0轉換
#define DIGITAL_COMPARE_FUNCTION:打開該宏,測試連續ADC0轉換
2.10.2測試程序介紹
選擇“Adc”工程,打開宏“#define STARTUP_BY_SOFTWARE”,編譯、加載,
- ADC0通道(P0.0)外接電壓源;
- 在ADC中斷服務程序中設置斷點,全速運行至斷點處,通過寄存器ADCL和ADCH可觀測外部電壓轉換值;
注:本項測試只完成一次AD轉換,要想再進行一次AD轉換,軟件需再次啟動AD轉換。
選擇“Adc”工程,打開宏“#define STARTUP_BY_HARDWARE”,編譯、加載,
- ADC0通道(P0.0)外接電壓源;
- 在ADC中斷服務程序中設置斷點,全速運行;
- 給P6.1口上升沿信號,可看到程序運行至斷點處,此時通過寄存器ADCL和ADCH可觀測外部電壓轉換值;
注:本項測試中,一次外部中斷只能觸發一次AD轉換,要想再進行一次AD轉換,需再次觸發外部中斷。
選擇“Adc”工程,打開宏“#define DIGITAL_COMPARE_FUNCTION”,編譯、加載,
- ADC0通道(P0.0)外接電壓源;
- 在ADC中斷服務程序中設置斷點,全速運行至斷點處,通過寄存器ADCL和ADCH可觀測外部電壓轉換值;
- 調節電壓后再全速運行,可看到程序再次運行至斷點處,通過寄存器ADCL和ADCH可觀測外部電壓轉換值;
- 重復步驟5),實現連續AD轉換。
2.10.3寄存器簡要介紹
| | |
| | |
| | AD模塊使能、啟動、比較使能、及轉換完成中斷標志、觸發源使能、事件觸發設置 |
| |
| | |
| |
| | |
| |
| | |
| |
| | |
| |
| |
寄存器的每一位詳細介紹見Spec。
DAC支持自校準功能,在精度要求較高的情況下,需先進行自校準,然后再正常使用DAC。
2.11.1測試程序介紹
選擇工程“Dac”,編譯、加載運行,測量DAC輸出口(P1.6)電壓約為2.5V;
注:本次測試程序選擇DACL執行寫操作觸發DAC輸出更新,選擇內建2.5V作為參考電壓,且輸入數字量為0xFFF,故轉換輸出電壓應該為2.5V。
實際應用中,可根據需要在初始化DAC時選擇其他觸發方式或決定是否開啟DAC補償。
2.11.2寄存器介紹
DACCON0
| | |
| | DAC轉換控制位 0: DAC 禁止 1: DAC使能 |
| | DAC輸出驅動選擇: 00:DAC輸出不帶緩沖器. 01:DAC輸出帶緩沖器(1倍) 1x:DAC輸出帶緩沖器(3倍) |
| | 鎖存器觸發源選擇 00: DACL執行寫操作觸發DAC輸出更新 01: 定時器2溢出觸發DAC輸出更新 10: 定時器3溢出觸發DAC輸出更新 11: PCA0定時器溢出觸發DAC輸出更新 |
| | |
| | DAC端口配置寄存器 0:P1.6作為為IO口 1:P1.6作為DAC輸出口 |
| | DAC中斷標志位 0:DAC轉換未完成. 1:DAC轉換完成,由硬件置1,軟件清0 |
DACCON1
| | |
| | DAC自校準操作控制(當DACOSEL[1:0] = 01或1x時,自校準功能有效) 0: 自校準關閉(自校準完成,硬件清零) 1: 自校準開啟(軟件開啟) |
| | DAC補償開關 0: 開啟DAC補償 1: 關閉DAC補償 |
| | 外部參考電壓輸入口選擇 0:P1.4作為I/O口 1:P1.4作為VREF輸入引腳 |
| | 內建電壓選擇: 0:內建2.5V 1:內建1.5V (內建電壓切換需要1ms的穩定時間) |
| | 內建1.5V/2.5V開關: 0:內建1.5V/2.5V關(P1.5作為I/O口) 1:內建1.5V/2.5V開(P1.5作為內部參考電壓輸出引腳) (內建電壓開啟需要1ms的穩定時間) |
| | DAC的參考源選擇: 00: 選擇VDD為基準電壓 01: 選擇外部VREF端口輸入為基準電壓 1x: 選擇內建電壓1.5V/2.5V為基準電壓 (DACSREF選擇內建電壓1.5V/2.5V時,確保REFON = 1,REFSEL選擇需要的內建電壓) |
DACCAL
| | |
| | DAC自校準補償電壓數據符號位: 0:正(轉換值比實際的值大) 1:負(轉換值比實際的值小) |
| | DAC自校準補償電壓數據 (DAC自校準完成,根據校準結果更新此寄存器。 當OFFSETSW = 0時,實際DAC的輸出是DACH:DACL與OFFSETDATA經過運算后的輸出值,以便DAC輸出精度更高 當OFFSETSW = 1時,DAC的輸出為DACH:DACL對應的模擬電壓) |
注:該寄存器,在執行DAC自校準功能時,硬件會自動更新;另外,軟件也可修改該寄存器,如,通常為了提高精度,軟件會對多次自校準后得到的DACCAL值求平均,然后再將其寫入DACCAL。
DACH、DACL
| | |
| | DAC數據 位3~0是12位DAC數據字的高4位。 位7~0是12位DAC數據字的低8位。 |
本次Demo程序給出了讀寫EEPROM的接口函數,如下:
1)UINT8 EEPromByteRead(UINT8 nAddrH,UINT8 nAddrL)
從EEPROM指定地址處讀取1個byte;
2)void EEPromByteProgram(UINT8 nAddrH,UINT8 nAddrL, UINT8 nData)
向EEPROM指定地址處寫一個byte;
3)void EEPromSectorErase(UINT8 nAddrH)
擦除EEPROM指定扇區中內容;
注:在對EEPROM進行擦除和寫操作之前,一定要關閉中斷,待操作結束后,才可打開中斷;另外,對Flash的讀、寫、擦除操作過程類似于類EEPROM操作,唯一區別是,在擦除或寫、讀之前應將FAC位清0。