码迷,mamicode.com
首页 > 其他好文 > 详细

模拟串口--基于STM8普通IO口的模拟串口驱动程序

时间:2014-10-13 18:19:37      阅读:1919      评论:0      收藏:0      [点我收藏+]

标签:模拟串口   串口驱动   stm8模拟串口   串口   

基于STM8普通IO口的模拟串口驱动程序


标准串口通讯数据的格式为:起始位(1) + 数据位(8) + 校验位(1) + 停止位(1)

串口通讯另外一个重要的的部分是设置波特率,波特率就是1秒钟内串口所传输的Bit(位)数。

关于采样频率为了较小读取或者发送串行数据的误差,我们采取了在N(我用的是4次)次中断中,取固定位置的读取的数据。


我以stm8中9600波特率计算的过程为例:(1秒钟传输9600位)

可以计算出传输1位所需要的时间 T1 = 1/9600 约为104us

由此可知,发送一位数据,定时器中断的时间间隔应为 104/4 = 26us(4倍采样频率)

stm8 内部晶振频率为16M,我采用8分频也就是2M,故MCU震荡周期为 1/2M = 0.5us

由上面的计算我们可以知道要发送一位数据,定时器中断的初值应设为为 26/0.5 =52


以上为相关数据的计算过程,下面是模拟串口驱动程序和注释:

定时器中断与IO口配置:

void TIM3_Configuration(void)
{
  TIM3_DeInit();
  TIM3_TimeBaseInit(TIM3_PRESCALER_8,52);        //52  104
  TIM3_ITConfig(TIM3_IT_UPDATE ,ENABLE);  
  TIM3_ARRPreloadConfig(ENABLE);
  TIM3_Cmd(ENABLE);                                                //DISABLE TIM3_Cmd(DISABLE)
}

//模拟串口引脚定义
#define SIM_UART_TX_PORT               GPIOC
#define SIM_UART_TX_PIN                GPIO_PIN_2
#define SimUartTxHigh()                (SIM_UART_TX_PORT->ODR |= (u8)(SIM_UART_TX_PIN))    
#define SimUartTxLow()                 (SIM_UART_TX_PORT->ODR &= (u8)(~SIM_UART_TX_PIN)) 

#define SIM_UART_RX_PORT               GPIOC
#define SIM_UART_RX_PIN                GPIO_PIN_3
#define SimUartRxStatus()              (SIM_UART_RX_PORT->IDR & SIM_UART_RX_PIN)

GPIO_Init(SIM_UART_RX_PORT, SIM_UART_RX_PIN,GPIO_MODE_IN_PU_NO_IT);       
  
GPIO_Init(SIM_UART_TX_PORT, SIM_UART_TX_PIN,GPIO_MODE_OUT_PP_LOW_FAST);     

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "global.h"

//默认采样频率为4倍  一下为16M晶振 8分频 后计数器的装载值
//9600B 104us发送一位  4倍采样频率 故为26us发送一位
#define  SIM_BAUDRATE_9600     52  
#define  SIM_BAUDRATE_4800     104
#define  SIM_BAUDRATE_2400     208

/* Private variables ---------------------------------------------------------*/
u8 RxByteIndex;        //接收字节索引
u8 RxSampFreq;         //采样频率控制 1/4
u8 TxXKCnt = 3;        //需要发送数据包的字节数
u8 SimUartRxBuff[10];  //接收数据包缓冲
u8 SimUartTxBuff[10] = {0x55, 0xaa, 0x66};
bool IsSimUartRxFinish;//是否接收完成标志
bool IsSimUartRecv;    //模拟串口是否处于接收状态


/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
void <span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">InterruptSimUart</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">(void);</span>
static void Drv_SimUartTxByte(void);
static void Drv_SimUartRxByte(void);

/*******************************************************************************
#Function      :   InterruptSimUart 
#Description   :   模拟串口中断调用程序  切换发送与接收
#Parameter     :   NULL
#Return        :   NULL
#AuthorAndData :   huangzhigang 20141013
*******************************************************************************/
void InterruptSimUart(void)
{
   if(IsSimUartRxFinish)   //接收完成后立刻发送数据  也可以自己定义什么时候发送数据
   {     
      IsSimUartRxFinish = FALSE;
      IsSimUartRecv = FALSE;
   }
   
   if(IsSimUartRecv)
   {
      Drv_SimUartRxByte();
   }
   else
   {
      Drv_SimUartTxByte();
   }
}

/*******************************************************************************
#Function      :   Drv_SimUartRxByte 
#Description   :   模拟串口接收函数
#Parameter     :   NULL
#Return        :   NULL
#AuthorAndData :   huangzhigang 20141013
*******************************************************************************/
static void Drv_SimUartRxByte(void)
{
    static u8 RxBitNum;    //接收位计数
    static u8 Verify;      //校验码
    static u8 OverTime;    //接收超时计数
    static u8 s_u8Rxbuff;  //一字节接收缓存

    if(SimUartRxStatus())
    {
        OverTime++;
    }
    else 
    {
         OverTime = 0;
    }

    if(OverTime > 44)
    {
        OverTime = 45;
        RxByteIndex = 0;
        RxBitNum = 0;
    }


    if((SimUartRxStatus()) && (RxBitNum == 0))
    {
        RxSampFreq = 0;
    }
    else 
    {
       ++RxSampFreq;   
    }

    if(RxSampFreq == 1)
    {
        if(RxBitNum == 0)                                           //低电平,起始位bit0
        {
            if(!SimUartRxStatus())                                  
            {
                Verify = 0;
                s_u8Rxbuff = 0;
                RxBitNum++;
            }
        }
        else if((RxBitNum > 0) && (RxBitNum < 9))                   //数据位  bit1~8
        {
            if(SimUartRxStatus())                                   //高电平
            {
                s_u8Rxbuff = s_u8Rxbuff | (0x01 << (RxBitNum -1));
                Verify++;
            }

            RxBitNum++;
        }
        else if(RxBitNum == 9)                                      //校验位  bit9
        {
            RxBitNum++;

            if(Verify & 0x01)
            {
                if(SimUartRxStatus()) {RxBitNum = 0;}               //奇校验
            }
            else
            {
                if(!SimUartRxStatus()) {RxBitNum = 0;}       
            }
            
        }
        else if(RxBitNum == 10)                                     //停止位 bit10 
        {
            if(SimUartRxStatus())                                       
            {
                RxBitNum = 0;

                if(RxByteIndex == 0)                                //头码1为0X55
                {
                    if(s_u8Rxbuff == 0x55)
                    {
                        SimUartRxBuff[RxByteIndex] = s_u8Rxbuff;
                        RxByteIndex++;
                    }
                    else
                    {
                        RxByteIndex = 0;
                    }
                    
                    //TEST  测试  接收到一字节数据后马上回复 
//                    IsSimUartRxFinish = TRUE;
                }
                else if(RxByteIndex == 1)                           //头码2为0Xaa
                {
                    if(s_u8Rxbuff == 0xaa)
                    {
                        SimUartRxBuff[RxByteIndex] = s_u8Rxbuff;
                        RxByteIndex++;
                    }
                    else
                    {
                        s_u8Rxbuff = 0;
                    }
                }
                else
                {
                      SimUartRxBuff[RxByteIndex] = s_u8Rxbuff;                             
                      RxByteIndex++;

                      if(RxByteIndex >= 2)                            //接收完一个数据包
                      {
                         //TODO: 20141013 hzg 验证校验码
                         RxByteIndex = 0;
                         IsSimUartRxFinish = TRUE;
                      }
                }
            }
        }
        else 
        {
            RxBitNum = 0;
        }
    }
    else if(RxSampFreq > 3)
    {
        RxSampFreq = 0;
    } 
    
}

/*******************************************************************************
#Function      :   Drv_SimUartTxByte 
#Description   :   模拟串口发送函数  
#Parameter     :   NULL
#Return        :   NULL
#AuthorAndData :   huangzhigang 20141013
*******************************************************************************/
void Drv_SimUartTxByte(void)
{
    static bool SendFinish = TRUE;  //发送完成标志
    static u8 Verify;               //奇偶校验
    static u8 TxSampFreq = 0;       //发送计数  采样4次
    static u8 BitNum = 0;           //位计数
    static u8 ByteLock;             //发送字节锁定(防止在发送途中 发送数字被改变)
    static u8 TxIndex = 0;          //当前发送索引


    if(SendFinish)
    {
       SendFinish = FALSE;
       RxSampFreq = 0;
       BitNum = 0;
       
       if(TxIndex < TxXKCnt)        //控制发送的字节
       {
          ByteLock = SimUartTxBuff[TxIndex];
          TxIndex++;
          RxByteIndex = 0;
       }
       else          
       {
          IsSimUartRecv = TRUE;
          SendFinish = TRUE;
          TIM3->ARRH = (uint8_t)(52 >> 8);   //定时器3计数器重装初值
          TIM3->ARRL = (uint8_t)(52);
          //            TxXKCnt = 0;
          TxIndex = 0;
       }
    }
    
    if(++TxSampFreq > 3)
    {
        if(BitNum == 0)                             //起始位
        {
            Verify = 0;
            SimUartTxLow();
            BitNum++;
        }
        else if((BitNum >0) && (BitNum < 9))        //数据位
        {
            if(0x01 & (ByteLock >> (BitNum-1)))     //先发低位
            {
                SimUartTxHigh();
                Verify++;
            }
            else
            {
                SimUartTxLow();
            }
            BitNum++;
        }
        else if(BitNum == 9)                        //校验位
        {
            if(0x01 & Verify)                       //奇校验  
            {
                SimUartTxLow();                     //有奇数个1 则发送0 
            }
            else
            {
                SimUartTxHigh();                    //有偶数个1则发送1
            }
            BitNum++;
        }
        else if(BitNum == 10)                       //停止位
        {
            SimUartTxHigh();
            SendFinish = TRUE;
            BitNum = 0;
        }
        
        TxSampFreq = 0;
    }
}











模拟串口--基于STM8普通IO口的模拟串口驱动程序

标签:模拟串口   串口驱动   stm8模拟串口   串口   

原文地址:http://blog.csdn.net/a656343072/article/details/40047591

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!