51单片机IO口模拟UART串口通信

Posted wuhh123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机IO口模拟UART串口通信相关的知识,希望对你有一定的参考价值。

#include <reg52.h>
#include "main.h"
#include "smartcard.h"
#include "stdio.h"

typedef enum false, true bool;

#if 0
sbit PIN_RXD = P1^0; //接收发送同一个引脚定义
sbit PIN_TXD = P1^0; //接收发送同一个发送引脚定义
sbit PIN_CLK = P3^1; //智能卡时钟引脚定义
sbit PIN_3v5v = P3^2; //智能卡3v_5v引脚定义
sbit PIN_RST = P3^3; //智能卡复位引脚定义
sbit PIN_CMDVCC = P3^4; //智能卡CMD引脚定义
#else
// test Parity
sbit PIN_RXD = P1^0; //接收 脚定义
sbit PIN_TXD = P1^2; //发送 脚定义
sbit PIN_CLK = P3^5; //智能卡时钟引脚定义
sbit PIN_3v5v = P3^2; //智能卡3v_5v引脚定义
sbit PIN_RST = P3^3; //智能卡复位引脚定义
sbit PIN_CMDVCC = P3^4; //智能卡CMD引脚定义

sbit Test_CLK = P0^3; //接收 脚定义

 

#endif

bit RxdOrTxd = 0; //指示当前状态为接收还是发送
bit RxdEnd = 0; //接收结束标志
bit TxdEnd = 0; //发送结束标志
uint8_t RxdBuf = 0; //接收缓冲器
uint8_t TxdBuf = 0; //发送缓冲器
void ConfigUART(unsigned int baud);
void StartTXD(unsigned char dat);
void StartRXD();
void test_IO();

//通过嵌套宏定义,制作一张包括0~255各个数字中包含1的个数,其中包含偶数个1,则ParityTable256[i]=0,否则ParityTable256[i]=1;


static const bool ParityTable256[256] =

#define P2(n) n, n^1, n^1, n
#define P4(n) P2(n), P2(n^1), P2(n^1), P2(n)
#define P6(n) P4(n), P4(n^1), P4(n^1), P4(n)
P6(0), P6(1), P6(1), P6(0)
;


void mainb()
EA = 1; //开总中断
ConfigUART(9600);//配置波特率为 9600
while (1)
while (PIN_RXD); //等待接收引脚出现低电平,即起始位
StartRXD(); //启动接收
while (!RxdEnd); //等待接收完成
StartTXD(RxdBuf+1); //接收到的数据+1 后,发送回去
while (!TxdEnd); //等待发送完成

return;

void SET_3v5v()

PIN_3v5v=1;

void RESET_3v5v()

PIN_3v5v=0;

void RST_SET(BitAction ResetState)

PIN_RST = ResetState;

void SET_CMVCC()

PIN_CMDVCC =1;

void RESET_CMVCC()

PIN_CMDVCC =0;


/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x02; //配置 T0 为模式 2
// TH0 = 256 - (11059200/6)/baud; //计算 T0 重载值
TH0 = 256 - (FOSC/12)/baud; //计算 T0 重载值


/* 启动串行接收 */
void StartRXD()


while (PIN_RXD);
//printf("PIN_RXD2=0x%02X\r\n", (int)PIN_RXD);
TL0 = 256 - ((256-TH0)>>1); //接收启动时的 T0 定时为半个波特率周期
ET0 = 1; //使能 T0 中断
TR0 = 1; //启动 T0
RxdEnd = 0; //清零接收结束标志
RxdOrTxd = 0; //设置当前状态为接收


/* 启动串行发送,dat-待发送字节数据 */
void StartTXD(uint8_t dat)
TxdBuf = dat; //待发送数据保存到发送缓冲器
TL0 = TH0; //T0 计数初值为重载值
ET0 = 1; //使能 T0 中断
TR0 = 1; //启动 T0
PIN_TXD = 0; //发送起始位
TxdEnd = 0; //清零发送结束标志
RxdOrTxd = 1; //设置当前状态为发送

uint16_t USART_ReceiveData(USART_TypeDef* USARTx)

/* Check the parameters */
// assert_param(IS_USART_ALL_PERIPH(USARTx));

/* Receive Data */
#if 0
uint16_t tt= USARTx->SR ;
USARTx->SR = tt & (uint16_t)0x3df; //wuhh add ,remove later

return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
#endif
return (uint16_t) RxdBuf;


void USART_SendData(USART_TypeDef* USARTx, uint8_t Data)

StartTXD(Data);

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)

FlagStatus bitstatus = RESET;
if (USART_FLAG== USART_FLAG_TC)
if (TxdEnd)

bitstatus = SET;

else

bitstatus = RESET;


if (USART_FLAG== USART_FLAG_RXNE)
if (RxdEnd)

bitstatus = SET;

else

bitstatus = RESET;

return bitstatus;

static bit polarity = 0; //输出智能卡时钟极性

#if 1

/* T0 中断服务函数,处理串行发送和接收 */
void InterruptTimer0() interrupt 1

static unsigned char cnt = 0; //位接收或发送计数
Test_CLK = !Test_CLK;

if (RxdOrTxd)
//串行发送处理
cnt++;
if (cnt <= 8) //低位在先依次发送 8bit 数据位
PIN_TXD = TxdBuf & 0x01;
TxdBuf >>= 1;
else
if (cnt == 9)
//发送停止位
PIN_TXD = 1;

else //发送结束
cnt = 0; //复位 bit 计数器
TR0 = 0; //关闭 T0
TxdEnd = 1; //置发送结束标志


else //串行接收处理
if (cnt == 0) //处理起始位
if (!PIN_RXD) //起始位为 0 时,清零接收缓冲器,准备接收数据位
RxdBuf = 0;
cnt++;

else //起始位不为 0 时,中止接收
TR0 = 0; //关闭 T0

else if (cnt <= 8) //处理 8 位数据位
RxdBuf >>= 1; //低位在先,所以将之前接收的位向右移
//接收脚为 1 时,缓冲器最高位置 1,
//而为 0 时不处理即仍保持移位后的 0
if (PIN_RXD)
RxdBuf |= 0x80;

cnt++;
else //停止位处理
cnt = 0; //复位 bit 计数器
TR0 = 0; //关闭 T0
if (PIN_RXD) //停止位为 1 时,方能认为数据有效
RxdEnd = 1; //置接收结束标志



#else
/* T0 中断服务函数,处理串行发送和接收 */

void InterruptTimer0() interrupt 1

static unsigned char cnt = 0; //位接收或发送计数
//test_IO();
#if 0
PIN_TXD = !PIN_TXD;
#else

if (RxdOrTxd) //串行发送处理
cnt++;
if (cnt <= 8) //低位在先依次发送 8bit 数据位
PIN_TXD = TxdBuf & 0x01;
TxdBuf >>= 1;
else if (cnt == 9) //奇偶位
PIN_TXD=ParityTable256[TxdBuf];
else if (cnt == 10) //发送停止位1 智能卡协议共两个停止位
PIN_TXD = 1;
else if (cnt == 11) //发送停止位2
PIN_TXD = 1;
else //发送结束
cnt = 0; //复位 bit 计数器
TR0 = 0; //关闭 T0
TxdEnd = 1; //置发送结束标志

else //串行接收处理
if (cnt == 0) //处理起始位
if (!PIN_RXD) //起始位为 0 时,清零接收缓冲器,准备接收数据位
RxdBuf = 0;
cnt++;
//printf("InterruptTimer 0\n");
else //起始位不为 0 时,中止接收
TR0 = 0; //关闭 T0
printf("InterruptTimer close\n");


else if (cnt <= 8) //处理 8 位数据位
RxdBuf >>= 1; //低位在先,所以将之前接收的位向右移
//接收脚为 1 时,缓冲器最高位置 1,
//而为 0 时不处理即仍保持移位后的 0
if (PIN_RXD)
RxdBuf |= 0x80;

printf("RxdBuf=0x%02X\r\n", (int)RxdBuf);
cnt++;
else //停止位处理
cnt = 0; //复位 bit 计数器
TR0 = 0; //关闭 T0
if (PIN_RXD) //停止位为 1 时,方能认为数据有效
RxdEnd = 1; //置接收结束标志



#endif

#endif

以上是关于51单片机IO口模拟UART串口通信的主要内容,如果未能解决你的问题,请参考以下文章

vb程序编写模拟串口

51单片机串口通讯

C51 串口

用单片机实现SPI-UART的转换

单片机的串口通信

stm32 普通IO口模拟串口通信