首页 > 代码库 > 单线通讯--单数据线自定义通讯驱动程序

单线通讯--单数据线自定义通讯驱动程序

单数据线自定义通讯驱动程序


简介:在双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);                                                            //使能计数
}

50us中断函数:

/*******************************************************************************
#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++;  
   }
}


单线通讯--单数据线自定义通讯驱动程序