使用51單片機Timer2模擬一個半雙工串口的c語言代碼
- /************* 功能說明 **************
- 使用STC15系列的Timer2做的模擬串口. P3.0接收, P3.1發送, 半雙工.
- 假定測試芯片的工作頻率為22118400Hz. 時鐘為5.5296MHZ ~ 35MHZ.
- 波特率高,則時鐘也要選高, 優先使用 22.1184MHZ, 11.0592MHZ.
- 測試方法: 上位機發送數據, MCU收到數據后原樣返回.
- 串口固定設置: 1位起始位, 8位數據位, 1位停止位, 波特率在范圍如下.
- 1200 ~ 115200 bps @ 33.1776MHZ
- 600 ~ 115200 bps @ 22.1184MHZ
- 600 ~ 76800 bps @ 18.4320MHZ
- 300 ~ 57600 bps @ 11.0592MHZ
- 150 ~ 19200 bps @ 5.5296MHZ
- ******************************************/
- #include <reg52.h>
- #define MAIN_Fosc 22118400UL //定義主時鐘
- #define UART3_Baudrate 115200UL //定義波特率
- #define RX_Lenth 32 //接收長度
- #define UART3_BitTime (MAIN_Fosc / UART3_Baudrate)
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- sfr IE2 = 0xAF;
- sfr AUXR = 0x8E;
- sfr INT_CLKO = 0x8F;
- sfr T2H = 0xD6;
- sfr T2L = 0xD7;
- u8 Tx3_read; //發送讀指針
- u8 Rx3_write; //接收寫指針
- u8 idata buf3[RX_Lenth]; //接收緩沖
- u16 RxTimeOut;
- bit B_RxOk; //接收結束標志
- //===================== 模擬串口相關===========================
- sbit P_RX3 = P3^0; //定義模擬串口接收IO
- sbit P_TX3 = P3^1; //定義模擬串口發送IO
- u8 Tx3_DAT; // 發送移位變量, 用戶不可見
- u8 Rx3_DAT; // 接收移位變量, 用戶不可見
- u8 Tx3_BitCnt; // 發送數據的位計數器, 用戶不可見
- u8 Rx3_BitCnt; // 接收數據的位計數器, 用戶不可見
- u8 Rx3_BUF; // 接收到的字節, 用戶讀取
- u8 Tx3_BUF; // 要發送的字節, 用戶寫入
- bit Rx3_Ring; // 正在接收標志, 低層程序使用, 用戶程序不可見
- bit Tx3_Ting; // 正在發送標志, 用戶置1請求發送, 底層發送完成清0
- bit RX3_End; // 接收到一個字節, 用戶查詢 并清0
- //=============================================================
- void UART_Init(void);
- /******************** 主函數 **************************/
- void main(void)
- {
-
- UART_Init(); //PCA初始化
- EA = 1;
-
- while (1) //user's function
- {
- if (RX3_End) // 檢測是否收到一個字節
- {
- RX3_End = 0; // 清除標志
- buf3[Rx3_write] = Rx3_BUF; // 寫入緩沖
- if(++Rx3_write >= RX_Lenth) Rx3_write = 0; // 指向下一個位置, 溢出檢測
- RxTimeOut = 1000; //裝載超時時間
- }
- if(RxTimeOut != 0) // 超時時間是否非0?
- {
- if(--RxTimeOut == 0) // (超時時間 - 1) == 0?
- {
- B_RxOk = 1;
- AUXR &= ~(1<<4); //Timer2 停止運行
- INT_CLKO &= ~(1 << 6); //禁止INT4中斷
- T2H = (65536 - UART3_BitTime) / 256; //數據位
- T2L = (65536 - UART3_BitTime) % 256; //數據位
- AUXR |= (1<<4); //Timer2 開始運行
- }
- }
-
- if(B_RxOk) // 檢測是否接收OK?
- {
- if (!Tx3_Ting) // 檢測是否發送空閑
- {
- if (Tx3_read != Rx3_write) // 檢測是否收到過字符
- {
- Tx3_BUF = buf3[Tx3_read]; // 從緩沖讀一個字符發送
- Tx3_Ting = 1; // 設置發送標志
- if(++Tx3_read >= RX_Lenth) Tx3_read = 0; // 指向下一個位置, 溢出檢測
- }
- else
- {
- B_RxOk = 0;
- AUXR &= ~(1<<4); //Timer2 停止運行
- INT_CLKO |= (1 << 6); //允許INT4中斷
- }
- }
- }
- }
- }
- //========================================================================
- // 函數: void UART_Init(void)
- // 描述: UART初始化程序.
- // 參數: none
- // 返回: none.
- // 版本: V1.0, 2013-11-22
- //========================================================================
- void UART_Init(void)
- {
- Tx3_read = 0;
- Rx3_write = 0;
- Tx3_Ting = 0;
- Rx3_Ring = 0;
- RX3_End = 0;
- Tx3_BitCnt = 0;
- RxTimeOut = 0;
- B_RxOk = 0;
- AUXR &= ~(1<<4); // Timer2 停止運行
- T2H = (65536 - UART3_BitTime) / 256; // 數據位
- T2L = (65536 - UART3_BitTime) % 256; // 數據位
- INT_CLKO |= (1 << 6); // 允許INT4中斷
- IE2 |= (1<<2); // 允許Timer2中斷
- AUXR |= (1<<2); // 1T
- }
- //======================================================================
- //========================================================================
- // 函數: void timer2_int (void) interrupt 12
- // 描述: Timer2中斷處理程序.
- // 參數: None
- // 返回: none.
- // 版本: V1.0, 2012-11-22
- //========================================================================
- void timer2_int (void) interrupt 12
- {
- if(Rx3_Ring) //已收到起始位
- {
- if (--Rx3_BitCnt == 0) //接收完一幀數據
- {
- Rx3_Ring = 0; //停止接收
- Rx3_BUF = Rx3_DAT; //存儲數據到緩沖區
- RX3_End = 1;
- AUXR &= ~(1<<4); //Timer2 停止運行
- INT_CLKO |= (1 << 6); //允許INT4中斷
- }
- else
- {
- Rx3_DAT >>= 1; //把接收的單b數據 暫存到 RxShiftReg(接收緩沖)
- if(P_RX3) Rx3_DAT |= 0x80; //shift RX data to RX buffer
- }
- }
- if(Tx3_Ting) // 不發送, 退出
- {
- if(Tx3_BitCnt == 0) //發送計數器為0 表明單字節發送還沒開始
- {
- P_TX3 = 0; //發送開始位
- Tx3_DAT = Tx3_BUF; //把緩沖的數據放到發送的buff
- Tx3_BitCnt = 9; //發送數據位數 (8數據位+1停止位)
- }
- else //發送計數器為非0 正在發送數據
- {
- if (--Tx3_BitCnt == 0) //發送計數器減為0 表明單字節發送結束
- {
- P_TX3 = 1; //送停止位數據
- Tx3_Ting = 0; //發送停止
- }
- else
- {
- Tx3_DAT >>= 1; //把最低位送到 CY(益處標志位)
- P_TX3 = CY; //發送一個bit數據
- }
- }
- }
- }
- /********************* INT4中斷函數 *************************/
- void Ext_INT4 (void) interrupt 16
- {
- AUXR &= ~(1<<4); //Timer2 停止運行
- T2H = (65536 - (UART3_BitTime / 2 + UART3_BitTime)) / 256; //起始位 + 半個數據位
- T2L = (65536 - (UART3_BitTime / 2 + UART3_BitTime)) % 256; //起始位 + 半個數據位
- AUXR |= (1<<4); //Timer2 開始運行
- Rx3_Ring = 1; //標志已收到起始位
- Rx3_BitCnt = 9; //初始化接收的數據位數(8個數據位+1個停止位)
-
- INT_CLKO &= ~(1 << 6); //禁止INT4中斷
- T2H = (65536 - UART3_BitTime) / 256; //數據位
- T2L = (65536 - UART3_BitTime) % 256; //數據位
- }
復制代碼
匯編語言:
- ;************* 功能說明 **************
- ;使用STC15系列的Timer2做的模擬串口. P3.0接收, P3.1發送, 半雙工.
- ;假定測試芯片的工作頻率為22118400Hz. 時鐘為5.5296MHZ ~ 35MHZ.
- ;波特率高,則時鐘也要選高, 優先使用 22.1184MHZ, 11.0592MHZ.
- ;測試方法: 上位機發送數據, MCU收到數據后原樣返回.
- ;串口固定設置: 1位起始位, 8位數據位, 1位停止位, 波特率在范圍如下.
- ;******************************************
- ;UART3_BitTime EQU 9216 ; 1200bps @ 11.0592MHz UART3_BitTime = (MAIN_Fosc / Baudrate)
- ;UART3_BitTime EQU 4608 ; 2400bps @ 11.0592MHz
- ;UART3_BitTime EQU 2304 ; 4800bps @ 11.0592MHz
- ;UART3_BitTime EQU 1152 ; 9600bps @ 11.0592MHz
- ;UART3_BitTime EQU 576 ;19200bps @ 11.0592MHz
- ;UART3_BitTime EQU 288 ;38400bps @ 11.0592MHz
- ;UART3_BitTime EQU 192 ;57600bps @ 11.0592MHz
- ;UART3_BitTime EQU 15360 ; 1200bps @ 18.432MHz
- ;UART3_BitTime EQU 7680 ; 2400bps @ 18.432MHz
- ;UART3_BitTime EQU 3840 ; 4800bps @ 18.432MHz
- ;UART3_BitTime EQU 1920 ; 9600bps @ 18.432MHz
- ;UART3_BitTime EQU 960 ;19200bps @ 18.432MHz
- ;UART3_BitTime EQU 480 ;38400bps @ 18.432MHz
- ;UART3_BitTime EQU 320 ;57600bps @ 18.432MHz
- ;UART3_BitTime EQU 18432 ; 1200bps @ 22.1184MHz
- ;UART3_BitTime EQU 9216 ; 2400bps @ 22.1184MHz
- ;UART3_BitTime EQU 4608 ; 4800bps @ 22.1184MHz
- ;UART3_BitTime EQU 2304 ; 9600bps @ 22.1184MHz
- ;UART3_BitTime EQU 1152 ;19200bps @ 22.1184MHz
- ;UART3_BitTime EQU 576 ;38400bps @ 22.1184MHz
- ;UART3_BitTime EQU 384 ;57600bps @ 22.1184MHz
- UART3_BitTime EQU 192 ;115200bps @ 22.1184MHz
- ;UART3_BitTime EQU 27648 ; 1200bps @ 33.1776MHz
- ;UART3_BitTime EQU 13824 ; 2400bps @ 33.1776MHz
- ;UART3_BitTime EQU 6912 ; 4800bps @ 33.1776MHz
- ;UART3_BitTime EQU 3456 ; 9600bps @ 33.1776MHz
- ;UART3_BitTime EQU 1728 ;19200bps @ 33.1776MHz
- ;UART3_BitTime EQU 864 ;38400bps @ 33.1776MHz
- ;UART3_BitTime EQU 576 ;57600bps @ 33.1776MHz
- ;UART3_BitTime EQU 288 ;115200bps @ 33.1776MHz
- IE2 DATA 0AFH
- AUXR DATA 08EH
- INT_CLKO DATA 08FH
- T2H DATA 0D6H
- T2L DATA 0D7H
- ;===================== 模擬串口相關 ===========================
- P_RX3 BIT P3.0 ; 定義模擬串口接收IO
- P_TX3 BIT P3.1 ; 定義模擬串口發送IO
- Rx3_Ring BIT 20H.0 ; 正在接收標志, 低層程序使用, 用戶程序不可見
- Tx3_Ting BIT 20H.1 ; 正在發送標志, 用戶置1請求發送, 底層發送完成清0
- RX3_End BIT 20H.2 ; 接收到一個字節, 用戶查詢 并清0
- B_RxOk BIT 20H.3 ; 接收結束標志
- Tx3_DAT DATA 30H ; 發送移位變量, 用戶不可見
- Rx3_DAT DATA 31H ; 接收移位變量, 用戶不可見
- Tx3_BitCnt DATA 32H ; 發送數據的位計數器, 用戶不可見
- Rx3_BitCnt DATA 33H ; 接收數據的位計數器, 用戶不可見
- Rx3_BUF DATA 34H ; 接收到的字節, 用戶讀取
- Tx3_BUF DATA 35H ; 要發送的字節, 用戶寫入
- ;=================================================================
- RxTimeOutH DATA 36H ;
- RxTimeOutL DATA 37H ;
- Tx3_read DATA 38H ; 發送讀指針
- Rx3_write DATA 39H ; 接收寫指針
- RX_Lenth EQU 32 ; 接收長度
- buf3 EQU 40H ; 40H ~ 5FH 接收緩沖
- STACK_POIRTER EQU 0D0H ;堆棧開始地址
- ;*******************************************************************
- ;*******************************************************************
- ORG 00H ;reset
- LJMP F_Main
- ORG 63H ;12 Timer2 interrupt
- LJMP F_Timer2_Interrupt
- ORG 83H ;16 INT4 interrupt
- LJMP F_INT4_Interrupt
- ;******************** 主程序 **************************/
- F_Main:
-
- MOV SP, #STACK_POIRTER
- MOV PSW, #0
- USING 0 ;選擇第0組R0~R7
- ;================= 用戶初始化程序 ====================================
- LCALL F_UART_Init ;UART初始化
- SETB EA
-
-
- ;=================== 主循環 ==================================
- L_MainLoop:
- JNB RX3_End, L_QuitRx3 ; 檢測是否收到一個字節
- CLR RX3_End ; 清除標志
- MOV A, #buf3
- ADD A, Rx3_write
- MOV R0, A
- MOV @R0, Rx3_BUF ; 寫入緩沖
- MOV RxTimeOutH, #HIGH 1000 ; 裝載超時時間
- MOV RxTimeOutL, #LOW 1000 ;
- INC Rx3_write ; 指向下一個位置
- MOV A, Rx3_write
- CLR C
- SUBB A, #RX_Lenth ; 溢出檢測
- JC L_QuitRx3
- MOV Rx3_write, #0
- L_QuitRx3:
- MOV A, RxTimeOutL
- ORL A, RxTimeOutH
- JZ L_QuitTimeOut ; 超時時間是否非0?
- MOV A, RxTimeOutL
- DEC RxTimeOutL ; (超時時間 - 1) == 0?
- JNZ $+4
- DEC RxTimeOutH
- DEC A
- ORL A, RxTimeOutH
- JNZ L_QuitTimeOut
-
- SETB B_RxOk ; 超時, 標志接收完成
- ANL AUXR, #NOT (1 SHL 4) ; Timer2 停止運行
- ANL INT_CLKO, #NOT (1 SHL 6) ; 禁止INT4中斷
- MOV T2H, #HIGH (65536 - UART3_BitTime) ;數據位
- MOV T2L, #LOW (65536 - UART3_BitTime) ;
- ORL AUXR, #(1 SHL 4) ; Timer2 開始運行
- L_QuitTimeOut:
- JNB B_RxOk, L_QuitTx3 ; 檢測是否接收OK?
- JB Tx3_Ting, L_QuitTx3 ; 檢測是否發送空閑
- MOV A, Tx3_read
- XRL A, Rx3_write
- JZ L_TxFinish ; 檢測是否發送完畢
- MOV A, #buf3
- ADD A, Tx3_read
- MOV R0, A
- MOV Tx3_BUF, @R0 ; 從緩沖讀一個字符發送
- SETB Tx3_Ting ; 設置發送標志
- INC Tx3_read ; 指向下一個字符位置
- MOV A, Tx3_read
- CLR C
- SUBB A, #RX_Lenth
- JC L_QuitTx3 ; 溢出檢測
- MOV Tx3_read, #0
- SJMP L_QuitTx3
- L_TxFinish:
- CLR B_RxOk
- ANL AUXR, #NOT (1 SHL 4) ; Timer2 停止運行
- ORL INT_CLKO, #(1 SHL 6) ; 允許INT4中斷
- L_QuitTx3:
- LJMP L_MainLoop
- ;=================== 主程序結束 ==================================
- ;========================================================================
- ; 函數: F_UART_Init
- ; 描述: UART初始化程序.
- ; 參數: none
- ; 返回: none.
- ; 版本: V1.0, 2013-11-22
- ;========================================================================
- F_UART_Init:
- MOV Tx3_read, #0
- MOV Rx3_write, #0
- CLR Tx3_Ting
- CLR RX3_End
- CLR Rx3_Ring
- MOV Tx3_BitCnt, #0
- MOV RxTimeOutH, #0
- MOV RxTimeOutL, #0
- CLR B_RxOk
- ANL AUXR, #NOT(1 SHL 4) ; Timer2 停止運行
- MOV T2H, #HIGH (65536 - UART3_BitTime) ; 數據位
- MOV T2L, #LOW (65536 - UART3_BitTime) ; 數據位
- ORL INT_CLKO, #(1 SHL 6) ; 允許INT4中斷
- ORL IE2, #(1 SHL 2) ; 允許Timer2中斷
- ORL AUXR, #(1 SHL 2) ; 1T模式
- RET
- ;======================================================================
- ;========================================================================
- ; 函數: void F_Timer2_Interrupt
- ; 描述: Timer2中斷處理程序.
- ; 參數: None
- ; 返回: none.
- ; 版本: V1.0, 2012-11-22
- ;========================================================================
- F_Timer2_Interrupt:
- PUSH PSW
- PUSH ACC
- JNB Rx3_Ring, L_QuitRx ; 已收到起始位
- DJNZ Rx3_BitCnt, L_RxBit ; 接收完一幀數據
-
- CLR Rx3_Ring ; 停止接收
- MOV Rx3_BUF, Rx3_DAT ; 存儲數據到緩沖區
- SETB RX3_End ;
- ANL AUXR, #NOT (1 SHL 4); Timer2 停止運行
- ORL INT_CLKO, #(1 SHL 6); 允許INT4中斷
- SJMP L_QuitRx
-
- L_RxBit:
- MOV A, Rx3_DAT ; 把接收的單b數據 暫存到 RxShiftReg(接收緩沖)
- MOV C, P_RX3
- RRC A
- MOV Rx3_DAT, A
- L_QuitRx:
- JNB Tx3_Ting, L_QuitTx ; 不發送, 退出
- MOV A, Tx3_BitCnt
- JNZ L_TxData ; 發送計數器為0 表明單字節發送還沒開始
- CLR P_TX3 ; 發送開始位
- MOV Tx3_DAT, Tx3_BUF ; 把緩沖的數據放到發送的buff
- MOV Tx3_BitCnt, #9 ; 發送數據位數 (8數據位+1停止位)
- SJMP L_QuitTx
- L_TxData: ; 發送計數器為非0 正在發送數據
- DJNZ Tx3_BitCnt, L_TxBit ; 發送計數器減為0 表明單字節發送結束
- SETB P_TX3 ; 送停止位數據
- CLR Tx3_Ting ; 發送停止
- SJMP L_QuitTx
- L_TxBit:
- MOV A, Tx3_DAT ; 把最低位送到 CY(益處標志位)
- RRC A
- MOV P_TX3, C ; 發送一個bit數據
- MOV Tx3_DAT, A
- L_QuitTx:
- POP ACC
- POP PSW
- RETI
-
- ;===================== INT4中斷函數 ==================================
- F_INT4_Interrupt:
- PUSH PSW
- PUSH ACC
- ANL AUXR, #NOT(1 SHL 4) ;Timer2 停止運行
- MOV T2H, #HIGH (65536 - (UART3_BitTime / 2 + UART3_BitTime)) ; 起始位 + 半個數據位
- MOV T2L, #LOW (65536 - (UART3_BitTime / 2 + UART3_BitTime)) ; 起始位 + 半個數據位
- ORL AUXR, #(1 SHL 4) ;Timer2 開始運行
- SETB Rx3_Ring ; 標志已收到起始位
- MOV Rx3_BitCnt, #9 ; 初始化接收的數據位數(8個數據位+1個停止位)
-
- ANL INT_CLKO, #NOT(1 SHL 6); //禁止INT4中斷
- MOV T2H, #HIGH (65536 - UART3_BitTime) ; 數據位
- MOV T2L, #LOW (65536 - UART3_BitTime) ; 數據位
- POP ACC
- POP PSW
- RETI
- END
復制代碼
所有資料51hei提供下載:
使用51單片機Timer2模擬一個半雙工串口.rar
(18.4 KB, 下載次數: 12)
2018-11-22 11:16 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|