单数据线自定义通讯驱动程序
简介:在双MCU单片机之间通过一根数据线(GPIO口)进行通讯的驱动(50us中断一次)
发送数据的数据头:定义为90次中断的低电平(50us*90 = 4.5ms) 270-90此中断的高电平(50us*180 = 9ms)
发送数据1:定义为11次中断的低电平(50us*11 = 550us) 45-11次中断的高电平(50us*34 = 1.7ms)
发送数据0:定义为11次中断的低电平(50us*11 = 550us) 22-11次中断的高电平(50us*11 = 550us)
两个MCU之间分为发送方和回复方,发送方首先发送数据包,回复方接收到完整的数据后 等待10ms 的延时后发送回 复数据给发送方。
STM8s定时器配置:
// 定时50us static void TIM4_Config(void) { TIM4_DeInit(); TIM4_TimeBaseInit(TIM4_PRESCALER_4,199); //50us TIM4->EGR = 0x01; //允许更新 TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE); //允许中断 TIM4_Cmd(ENABLE); //使能计数 }
/******************************************************************************* #Function : Interrupt_Time4Up #Description : 定时器中断运行,定时50us执行通讯驱动程序 #Parameter : NULL #Return : NULL #AuthorAndData : huangzhigang 20140915 *******************************************************************************/ void Interrupt_Time4Up(void) { if(!g_b1SciTxFlag) { s_SCIRxDriver(); //串行数据接收驱动函数 } else { s_SCITxDriver(); //串行数据发送驱动函数 } }
union STATUS_BIT_U uInterruptStatusBufFlag = {0}; //50us基础时钟 #define MSEC1 20 #define MSEC5_1 50 //u8 flag = 0; static void s_SCIRxDriver(void); union STATUS_BIT_U uSciRxStatusFlag = {0}; #define s_b1SciRxStartFlag uSciRxStatusFlag.cBit.bit0 //串行数据接收开始标志位 #define s_b1SciHighStatusFlag uSciRxStatusFlag.cBit.bit1 //串行高电平状态标志位 #define s_b1SciBootCodeFlag uSciRxStatusFlag.cBit.bit2 //引导码标志位 #define s_b1SciRxLowStatusFlag uSciRxStatusFlag.cBit.bit3 //串行接收低电平状态标志位 #define RX_BOOT_CODE_MIN 216 //13.5ms #define RX_BOOT_CODE_MAX 300 #define RX_DATA_CODE 36 //1.8ms static u8 s_u8SciDataStatusSum = 0; static u8 s_u8SciDataStatusBuf[5] = {0, 0, 0, 0, 0}; static u8 s_u8SciDataPoint = 0; static u16 s_u16SciRxCnt = 0; static u8 s_u8ByteCnt = 0; static u8 s_u8BitCnt = 0; u8 g_u8SciRxDataBuf[10] = {0}; static void s_SCITxDriver(void); union STATUS_BIT_U uSciTxStatusFlag = {0}; #define s_b1SciTxStatusFlag uSciTxStatusFlag.cBit.bit0 //串行发送状态标志位 #define s_b1SciTxBootCodeFlag uSciTxStatusFlag.cBit.bit1 //串行发送引导码标志位 #define s_b1SciTxBitStartFlag uSciTxStatusFlag.cBit.bit2 //串行发送位开始标志 #define s_b1SciTxLastByteFlag uSciTxStatusFlag.cBit.bit3 //判断是否发送最后字节 static u16 s_u16DataHigh = 0; static u16 s_u16DataLow = 0; static u16 s_u16SciTxTimer = 0; static u8 s_u8TxBit = 0; static u8 s_u8TxByte = 0; /*----------------------------------------------------------------------------*/ void Interrupt_Time4Up(); static void s_SCIRxDriver(void); static void s_SCITxDriver(void); /******************************************************************************* #Function : Interrupt_Time4Up #Description : 定时器中断运行,定时50us执行通讯驱动程序 #Parameter : NULL #Return : NULL #AuthorAndData : huangzhigang 20140915 *******************************************************************************/ void Interrupt_Time4Up(void) { if(!g_b1SciTxFlag) { s_SCIRxDriver(); //串行数据接收驱动函数 } else { s_SCITxDriver(); //串行数据发送驱动函数 } } /******************************************************************************* * 串行数据接收 *******************************************************************************/ static void s_SCIRxDriver(void) { s_u8SciDataStatusSum -= s_u8SciDataStatusBuf[s_u8SciDataPoint]; if(SciDataStatus) //串行数据状态 { s_u8SciDataStatusBuf[s_u8SciDataPoint] = 1; //1 } else { s_u8SciDataStatusBuf[s_u8SciDataPoint] = 0; //0 } s_u8SciDataStatusSum += s_u8SciDataStatusBuf[s_u8SciDataPoint]; s_u8SciDataPoint ++; if(s_u8SciDataPoint > 4) { s_u8SciDataPoint = 0; } if(s_u8SciDataStatusSum >= 3) //高电平处理 { if(s_b1SciRxStartFlag) //串行数据接收开始标志位 { s_u16SciRxCnt++; //串行接收数据计数 } s_b1SciHighStatusFlag = 1; } else { if(s_b1SciHighStatusFlag) { s_b1SciHighStatusFlag = 0; if(s_b1SciRxStartFlag) //串行接收开始标志位 { if(!s_b1SciBootCodeFlag) //引导码标志位 { if((s_u16SciRxCnt > RX_BOOT_CODE_MIN) && (s_u16SciRxCnt < RX_BOOT_CODE_MAX))//判断引导码 { s_b1SciBootCodeFlag = 1; } } else { if(s_u16SciRxCnt < RX_DATA_CODE) //脉宽小于1.8ms { g_u8SciRxDataBuf[s_u8ByteCnt] &= (~(1 << s_u8BitCnt)); //0 } else { g_u8SciRxDataBuf[s_u8ByteCnt] |= (1 << s_u8BitCnt); //1 } s_u8BitCnt++; //位计数 if(s_u8BitCnt >= 8) { s_u8BitCnt = 0; s_u8ByteCnt ++; //字节计数 if(s_u8ByteCnt > SCI_RX_BYTE) { s_u8ByteCnt = 0; uSciRxStatusFlag.all = 0; g_b1SciRxFinishFlag = 1; g_b1SciCorrectFlag = 1; //通信正常标志位 } } } } else { s_b1SciRxStartFlag = 1; } s_u16SciRxCnt = 0; } s_u16SciRxCnt++; s_b1SciRxLowStatusFlag = 1; //串行接收低电平状态标志位 } if(s_u16SciRxCnt > 400) //串行接收计数大于400 出错了 { s_u16SciRxCnt = 0; uSciRxStatusFlag.all = 0; s_u8ByteCnt = 0; s_u8BitCnt = 0; } } /******************************************************************************* * 串行数据发送 *******************************************************************************/ static void s_SCITxDriver(void) { SciDataOut(); //串行数据输出 if(!s_b1SciTxBitStartFlag) //串行发送位开始标志判断 { s_b1SciTxBitStartFlag = 1; //串行发送位开始标志 s_u16SciTxTimer = 0; if(!s_b1SciTxBootCodeFlag) //串行发送引导码标志位判断 { s_b1SciTxBootCodeFlag = 1; s_u16DataHigh = 270; s_u16DataLow = 90; } else { if(g_u8SciTxData[s_u8TxByte] & (1 << s_u8TxBit)) //发送1 { s_u16DataHigh = 45; s_u16DataLow = 11; } else //发送0 { s_u16DataHigh = 22; s_u16DataLow = 11; } s_u8TxBit ++; //位计数 if(s_u8TxBit > 7) { s_u8TxBit = 0; s_u8TxByte++; //字节计数 if(s_u8TxByte > SCI_TX_BYTE) //判断是否发完一帧数据 { s_b1SciTxLastByteFlag = 1; //串行发送最后字节标志位 s_u8TxByte = 0; //发送字节清0 } } } } if(s_b1SciTxBitStartFlag) //串行发送位开始标志 { if(s_u16SciTxTimer == 0) //串行发送时间判断 { SciDataLow(); //数据线拉低 } else if(s_u16SciTxTimer == s_u16DataLow) //串行发送时间判断 { SciDataHigh(); //数据线拉高 } else if(s_u16SciTxTimer == s_u16DataHigh) //串行发送时间判断 { SciDataLow(); //数据线拉低 if(!s_b1SciTxLastByteFlag) //判断是否发送最后字节 { s_u16SciTxTimer = 0; //发送时间清0 s_b1SciTxBitStartFlag = 0; //串行发送位开始标志 } } else if(s_u16SciTxTimer == (s_u16DataHigh + 10)) //串行发送时间大于 高电平时间+10 出错了 { g_b1SciTxFlag = 0; s_b1SciTxLastByteFlag = 0; s_b1SciTxBootCodeFlag = 0; s_b1SciTxBitStartFlag = 0; SciDataIn(); //串行数据输入 } s_u16SciTxTimer++; } }
原文地址:http://blog.csdn.net/a656343072/article/details/39393661