標(biāo)題:
51單片機(jī)Timer2模擬半雙工串口的C語(yǔ)言和匯編代碼及注釋說(shuō)明
[打印本頁(yè)]
作者:
wuaxiang
時(shí)間:
2018-11-22 11:16
標(biāo)題:
51單片機(jī)Timer2模擬半雙工串口的C語(yǔ)言和匯編代碼及注釋說(shuō)明
使用51單片機(jī)Timer2模擬一個(gè)半雙工串口的c語(yǔ)言代碼
/************* 功能說(shuō)明 **************
使用STC15系列的Timer2做的模擬串口. P3.0接收, P3.1發(fā)送, 半雙工.
假定測(cè)試芯片的工作頻率為22118400Hz. 時(shí)鐘為5.5296MHZ ~ 35MHZ.
波特率高,則時(shí)鐘也要選高, 優(yōu)先使用 22.1184MHZ, 11.0592MHZ.
測(cè)試方法: 上位機(jī)發(fā)送數(shù)據(jù), MCU收到數(shù)據(jù)后原樣返回.
串口固定設(shè)置: 1位起始位, 8位數(shù)據(jù)位, 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 //定義主時(shí)鐘
#define UART3_Baudrate 115200UL //定義波特率
#define RX_Lenth 32 //接收長(zhǎng)度
#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; //發(fā)送讀指針
u8 Rx3_write; //接收寫(xiě)指針
u8 idata buf3[RX_Lenth]; //接收緩沖
u16 RxTimeOut;
bit B_RxOk; //接收結(jié)束標(biāo)志
//===================== 模擬串口相關(guān)===========================
sbit P_RX3 = P3^0; //定義模擬串口接收IO
sbit P_TX3 = P3^1; //定義模擬串口發(fā)送IO
u8 Tx3_DAT; // 發(fā)送移位變量, 用戶(hù)不可見(jiàn)
u8 Rx3_DAT; // 接收移位變量, 用戶(hù)不可見(jiàn)
u8 Tx3_BitCnt; // 發(fā)送數(shù)據(jù)的位計(jì)數(shù)器, 用戶(hù)不可見(jiàn)
u8 Rx3_BitCnt; // 接收數(shù)據(jù)的位計(jì)數(shù)器, 用戶(hù)不可見(jiàn)
u8 Rx3_BUF; // 接收到的字節(jié), 用戶(hù)讀取
u8 Tx3_BUF; // 要發(fā)送的字節(jié), 用戶(hù)寫(xiě)入
bit Rx3_Ring; // 正在接收標(biāo)志, 低層程序使用, 用戶(hù)程序不可見(jiàn)
bit Tx3_Ting; // 正在發(fā)送標(biāo)志, 用戶(hù)置1請(qǐng)求發(fā)送, 底層發(fā)送完成清0
bit RX3_End; // 接收到一個(gè)字節(jié), 用戶(hù)查詢(xún) 并清0
//=============================================================
void UART_Init(void);
/******************** 主函數(shù) **************************/
void main(void)
{
UART_Init(); //PCA初始化
EA = 1;
while (1) //user's function
{
if (RX3_End) // 檢測(cè)是否收到一個(gè)字節(jié)
{
RX3_End = 0; // 清除標(biāo)志
buf3[Rx3_write] = Rx3_BUF; // 寫(xiě)入緩沖
if(++Rx3_write >= RX_Lenth) Rx3_write = 0; // 指向下一個(gè)位置, 溢出檢測(cè)
RxTimeOut = 1000; //裝載超時(shí)時(shí)間
}
if(RxTimeOut != 0) // 超時(shí)時(shí)間是否非0?
{
if(--RxTimeOut == 0) // (超時(shí)時(shí)間 - 1) == 0?
{
B_RxOk = 1;
AUXR &= ~(1<<4); //Timer2 停止運(yùn)行
INT_CLKO &= ~(1 << 6); //禁止INT4中斷
T2H = (65536 - UART3_BitTime) / 256; //數(shù)據(jù)位
T2L = (65536 - UART3_BitTime) % 256; //數(shù)據(jù)位
AUXR |= (1<<4); //Timer2 開(kāi)始運(yùn)行
}
}
if(B_RxOk) // 檢測(cè)是否接收OK?
{
if (!Tx3_Ting) // 檢測(cè)是否發(fā)送空閑
{
if (Tx3_read != Rx3_write) // 檢測(cè)是否收到過(guò)字符
{
Tx3_BUF = buf3[Tx3_read]; // 從緩沖讀一個(gè)字符發(fā)送
Tx3_Ting = 1; // 設(shè)置發(fā)送標(biāo)志
if(++Tx3_read >= RX_Lenth) Tx3_read = 0; // 指向下一個(gè)位置, 溢出檢測(cè)
}
else
{
B_RxOk = 0;
AUXR &= ~(1<<4); //Timer2 停止運(yùn)行
INT_CLKO |= (1 << 6); //允許INT4中斷
}
}
}
}
}
//========================================================================
// 函數(shù): void UART_Init(void)
// 描述: UART初始化程序.
// 參數(shù): 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 停止運(yùn)行
T2H = (65536 - UART3_BitTime) / 256; // 數(shù)據(jù)位
T2L = (65536 - UART3_BitTime) % 256; // 數(shù)據(jù)位
INT_CLKO |= (1 << 6); // 允許INT4中斷
IE2 |= (1<<2); // 允許Timer2中斷
AUXR |= (1<<2); // 1T
}
//======================================================================
//========================================================================
// 函數(shù): void timer2_int (void) interrupt 12
// 描述: Timer2中斷處理程序.
// 參數(shù): None
// 返回: none.
// 版本: V1.0, 2012-11-22
//========================================================================
void timer2_int (void) interrupt 12
{
if(Rx3_Ring) //已收到起始位
{
if (--Rx3_BitCnt == 0) //接收完一幀數(shù)據(jù)
{
Rx3_Ring = 0; //停止接收
Rx3_BUF = Rx3_DAT; //存儲(chǔ)數(shù)據(jù)到緩沖區(qū)
RX3_End = 1;
AUXR &= ~(1<<4); //Timer2 停止運(yùn)行
INT_CLKO |= (1 << 6); //允許INT4中斷
}
else
{
Rx3_DAT >>= 1; //把接收的單b數(shù)據(jù) 暫存到 RxShiftReg(接收緩沖)
if(P_RX3) Rx3_DAT |= 0x80; //shift RX data to RX buffer
}
}
if(Tx3_Ting) // 不發(fā)送, 退出
{
if(Tx3_BitCnt == 0) //發(fā)送計(jì)數(shù)器為0 表明單字節(jié)發(fā)送還沒(méi)開(kāi)始
{
P_TX3 = 0; //發(fā)送開(kāi)始位
Tx3_DAT = Tx3_BUF; //把緩沖的數(shù)據(jù)放到發(fā)送的buff
Tx3_BitCnt = 9; //發(fā)送數(shù)據(jù)位數(shù) (8數(shù)據(jù)位+1停止位)
}
else //發(fā)送計(jì)數(shù)器為非0 正在發(fā)送數(shù)據(jù)
{
if (--Tx3_BitCnt == 0) //發(fā)送計(jì)數(shù)器減為0 表明單字節(jié)發(fā)送結(jié)束
{
P_TX3 = 1; //送停止位數(shù)據(jù)
Tx3_Ting = 0; //發(fā)送停止
}
else
{
Tx3_DAT >>= 1; //把最低位送到 CY(益處標(biāo)志位)
P_TX3 = CY; //發(fā)送一個(gè)bit數(shù)據(jù)
}
}
}
}
/********************* INT4中斷函數(shù) *************************/
void Ext_INT4 (void) interrupt 16
{
AUXR &= ~(1<<4); //Timer2 停止運(yùn)行
T2H = (65536 - (UART3_BitTime / 2 + UART3_BitTime)) / 256; //起始位 + 半個(gè)數(shù)據(jù)位
T2L = (65536 - (UART3_BitTime / 2 + UART3_BitTime)) % 256; //起始位 + 半個(gè)數(shù)據(jù)位
AUXR |= (1<<4); //Timer2 開(kāi)始運(yùn)行
Rx3_Ring = 1; //標(biāo)志已收到起始位
Rx3_BitCnt = 9; //初始化接收的數(shù)據(jù)位數(shù)(8個(gè)數(shù)據(jù)位+1個(gè)停止位)
INT_CLKO &= ~(1 << 6); //禁止INT4中斷
T2H = (65536 - UART3_BitTime) / 256; //數(shù)據(jù)位
T2L = (65536 - UART3_BitTime) % 256; //數(shù)據(jù)位
}
復(fù)制代碼
匯編語(yǔ)言:
;************* 功能說(shuō)明 **************
;使用STC15系列的Timer2做的模擬串口. P3.0接收, P3.1發(fā)送, 半雙工.
;假定測(cè)試芯片的工作頻率為22118400Hz. 時(shí)鐘為5.5296MHZ ~ 35MHZ.
;波特率高,則時(shí)鐘也要選高, 優(yōu)先使用 22.1184MHZ, 11.0592MHZ.
;測(cè)試方法: 上位機(jī)發(fā)送數(shù)據(jù), MCU收到數(shù)據(jù)后原樣返回.
;串口固定設(shè)置: 1位起始位, 8位數(shù)據(jù)位, 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
;===================== 模擬串口相關(guān) ===========================
P_RX3 BIT P3.0 ; 定義模擬串口接收IO
P_TX3 BIT P3.1 ; 定義模擬串口發(fā)送IO
Rx3_Ring BIT 20H.0 ; 正在接收標(biāo)志, 低層程序使用, 用戶(hù)程序不可見(jiàn)
Tx3_Ting BIT 20H.1 ; 正在發(fā)送標(biāo)志, 用戶(hù)置1請(qǐng)求發(fā)送, 底層發(fā)送完成清0
RX3_End BIT 20H.2 ; 接收到一個(gè)字節(jié), 用戶(hù)查詢(xún) 并清0
B_RxOk BIT 20H.3 ; 接收結(jié)束標(biāo)志
Tx3_DAT DATA 30H ; 發(fā)送移位變量, 用戶(hù)不可見(jiàn)
Rx3_DAT DATA 31H ; 接收移位變量, 用戶(hù)不可見(jiàn)
Tx3_BitCnt DATA 32H ; 發(fā)送數(shù)據(jù)的位計(jì)數(shù)器, 用戶(hù)不可見(jiàn)
Rx3_BitCnt DATA 33H ; 接收數(shù)據(jù)的位計(jì)數(shù)器, 用戶(hù)不可見(jiàn)
Rx3_BUF DATA 34H ; 接收到的字節(jié), 用戶(hù)讀取
Tx3_BUF DATA 35H ; 要發(fā)送的字節(jié), 用戶(hù)寫(xiě)入
;=================================================================
RxTimeOutH DATA 36H ;
RxTimeOutL DATA 37H ;
Tx3_read DATA 38H ; 發(fā)送讀指針
Rx3_write DATA 39H ; 接收寫(xiě)指針
RX_Lenth EQU 32 ; 接收長(zhǎng)度
buf3 EQU 40H ; 40H ~ 5FH 接收緩沖
STACK_POIRTER EQU 0D0H ;堆棧開(kāi)始地址
;*******************************************************************
;*******************************************************************
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
;================= 用戶(hù)初始化程序 ====================================
LCALL F_UART_Init ;UART初始化
SETB EA
;=================== 主循環(huán) ==================================
L_MainLoop:
JNB RX3_End, L_QuitRx3 ; 檢測(cè)是否收到一個(gè)字節(jié)
CLR RX3_End ; 清除標(biāo)志
MOV A, #buf3
ADD A, Rx3_write
MOV R0, A
MOV @R0, Rx3_BUF ; 寫(xiě)入緩沖
MOV RxTimeOutH, #HIGH 1000 ; 裝載超時(shí)時(shí)間
MOV RxTimeOutL, #LOW 1000 ;
INC Rx3_write ; 指向下一個(gè)位置
MOV A, Rx3_write
CLR C
SUBB A, #RX_Lenth ; 溢出檢測(cè)
JC L_QuitRx3
MOV Rx3_write, #0
L_QuitRx3:
MOV A, RxTimeOutL
ORL A, RxTimeOutH
JZ L_QuitTimeOut ; 超時(shí)時(shí)間是否非0?
MOV A, RxTimeOutL
DEC RxTimeOutL ; (超時(shí)時(shí)間 - 1) == 0?
JNZ $+4
DEC RxTimeOutH
DEC A
ORL A, RxTimeOutH
JNZ L_QuitTimeOut
SETB B_RxOk ; 超時(shí), 標(biāo)志接收完成
ANL AUXR, #NOT (1 SHL 4) ; Timer2 停止運(yùn)行
ANL INT_CLKO, #NOT (1 SHL 6) ; 禁止INT4中斷
MOV T2H, #HIGH (65536 - UART3_BitTime) ;數(shù)據(jù)位
MOV T2L, #LOW (65536 - UART3_BitTime) ;
ORL AUXR, #(1 SHL 4) ; Timer2 開(kāi)始運(yùn)行
L_QuitTimeOut:
JNB B_RxOk, L_QuitTx3 ; 檢測(cè)是否接收OK?
JB Tx3_Ting, L_QuitTx3 ; 檢測(cè)是否發(fā)送空閑
MOV A, Tx3_read
XRL A, Rx3_write
JZ L_TxFinish ; 檢測(cè)是否發(fā)送完畢
MOV A, #buf3
ADD A, Tx3_read
MOV R0, A
MOV Tx3_BUF, @R0 ; 從緩沖讀一個(gè)字符發(fā)送
SETB Tx3_Ting ; 設(shè)置發(fā)送標(biāo)志
INC Tx3_read ; 指向下一個(gè)字符位置
MOV A, Tx3_read
CLR C
SUBB A, #RX_Lenth
JC L_QuitTx3 ; 溢出檢測(cè)
MOV Tx3_read, #0
SJMP L_QuitTx3
L_TxFinish:
CLR B_RxOk
ANL AUXR, #NOT (1 SHL 4) ; Timer2 停止運(yùn)行
ORL INT_CLKO, #(1 SHL 6) ; 允許INT4中斷
L_QuitTx3:
LJMP L_MainLoop
;=================== 主程序結(jié)束 ==================================
;========================================================================
; 函數(shù): F_UART_Init
; 描述: UART初始化程序.
; 參數(shù): 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 停止運(yùn)行
MOV T2H, #HIGH (65536 - UART3_BitTime) ; 數(shù)據(jù)位
MOV T2L, #LOW (65536 - UART3_BitTime) ; 數(shù)據(jù)位
ORL INT_CLKO, #(1 SHL 6) ; 允許INT4中斷
ORL IE2, #(1 SHL 2) ; 允許Timer2中斷
ORL AUXR, #(1 SHL 2) ; 1T模式
RET
;======================================================================
;========================================================================
; 函數(shù): void F_Timer2_Interrupt
; 描述: Timer2中斷處理程序.
; 參數(shù): None
; 返回: none.
; 版本: V1.0, 2012-11-22
;========================================================================
F_Timer2_Interrupt:
PUSH PSW
PUSH ACC
JNB Rx3_Ring, L_QuitRx ; 已收到起始位
DJNZ Rx3_BitCnt, L_RxBit ; 接收完一幀數(shù)據(jù)
CLR Rx3_Ring ; 停止接收
MOV Rx3_BUF, Rx3_DAT ; 存儲(chǔ)數(shù)據(jù)到緩沖區(qū)
SETB RX3_End ;
ANL AUXR, #NOT (1 SHL 4); Timer2 停止運(yùn)行
ORL INT_CLKO, #(1 SHL 6); 允許INT4中斷
SJMP L_QuitRx
L_RxBit:
MOV A, Rx3_DAT ; 把接收的單b數(shù)據(jù) 暫存到 RxShiftReg(接收緩沖)
MOV C, P_RX3
RRC A
MOV Rx3_DAT, A
L_QuitRx:
JNB Tx3_Ting, L_QuitTx ; 不發(fā)送, 退出
MOV A, Tx3_BitCnt
JNZ L_TxData ; 發(fā)送計(jì)數(shù)器為0 表明單字節(jié)發(fā)送還沒(méi)開(kāi)始
CLR P_TX3 ; 發(fā)送開(kāi)始位
MOV Tx3_DAT, Tx3_BUF ; 把緩沖的數(shù)據(jù)放到發(fā)送的buff
MOV Tx3_BitCnt, #9 ; 發(fā)送數(shù)據(jù)位數(shù) (8數(shù)據(jù)位+1停止位)
SJMP L_QuitTx
L_TxData: ; 發(fā)送計(jì)數(shù)器為非0 正在發(fā)送數(shù)據(jù)
DJNZ Tx3_BitCnt, L_TxBit ; 發(fā)送計(jì)數(shù)器減為0 表明單字節(jié)發(fā)送結(jié)束
SETB P_TX3 ; 送停止位數(shù)據(jù)
CLR Tx3_Ting ; 發(fā)送停止
SJMP L_QuitTx
L_TxBit:
MOV A, Tx3_DAT ; 把最低位送到 CY(益處標(biāo)志位)
RRC A
MOV P_TX3, C ; 發(fā)送一個(gè)bit數(shù)據(jù)
MOV Tx3_DAT, A
L_QuitTx:
POP ACC
POP PSW
RETI
;===================== INT4中斷函數(shù) ==================================
F_INT4_Interrupt:
PUSH PSW
PUSH ACC
ANL AUXR, #NOT(1 SHL 4) ;Timer2 停止運(yùn)行
MOV T2H, #HIGH (65536 - (UART3_BitTime / 2 + UART3_BitTime)) ; 起始位 + 半個(gè)數(shù)據(jù)位
MOV T2L, #LOW (65536 - (UART3_BitTime / 2 + UART3_BitTime)) ; 起始位 + 半個(gè)數(shù)據(jù)位
ORL AUXR, #(1 SHL 4) ;Timer2 開(kāi)始運(yùn)行
SETB Rx3_Ring ; 標(biāo)志已收到起始位
MOV Rx3_BitCnt, #9 ; 初始化接收的數(shù)據(jù)位數(shù)(8個(gè)數(shù)據(jù)位+1個(gè)停止位)
ANL INT_CLKO, #NOT(1 SHL 6); //禁止INT4中斷
MOV T2H, #HIGH (65536 - UART3_BitTime) ; 數(shù)據(jù)位
MOV T2L, #LOW (65536 - UART3_BitTime) ; 數(shù)據(jù)位
POP ACC
POP PSW
RETI
END
復(fù)制代碼
所有資料51hei提供下載:
使用51單片機(jī)Timer2模擬一個(gè)半雙工串口.rar
(18.4 KB, 下載次數(shù): 12)
2018-11-22 11:16 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1