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