单数据线自定义通讯驱动程序
简介:在双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