使用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)
|