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

2020-03-23来源: eefocus关键字:模拟串口  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 InterruptSimUart(void);

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++;

[1] [2]
关键字:模拟串口  STM8  普通IO口  驱动程序 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic492346.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:分析解决“STM8L101单片机IO口模拟串口通讯发生的奇怪现象”
下一篇:STM8S那些破事

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

分析解决“STM8L101单片机IO口模拟串口通讯发生的奇怪现象”
如下:/**********************************************描述:用延时法模拟串口通讯,中断方式接收硬件:2MHz,内部默认16Mhz,8分频,STM8L101F3P6,RXD---PB7.TXD---PB4波特率:2400测试:上电后,分别发送0x01,0x02,0x03,3个字符。问题:第1次循环接收到的字符不正确,但第2次以后均正确时间:2012.07.26 于单位**********************************************/#include "stm8l10x.h"#include "stm8l10x_clk.h"#include "stm8l10x_gpio.h" 
发表于 2020-03-23
分析解决“STM8L101单片机IO口模拟串口通讯发生的奇怪现象”
STM8 普通IO配置模拟串口输出
高精度延时函数,但是是针对stm8在时钟频率是2mhz,且函数参数单位是1.5us的,但是最小延时只能是21us,无法把延时降到8.68us左右当时写出这个延时函数花费1-2天的时间去测试和验证,测试起来比较繁琐和麻烦)为了更快更有效的完成这个需求,本人采取扫描方式来找到自己想要的延时时间。前提要先写好io模拟串口驱动,本人在stm8平台上对PD3做串口输出。普通io模拟串口驱动分别写在了一个c文件和h文件中:.C:#include "analog_uart.h" uint16_t ANALOG_TICK_N = 1;// 115200bps:18 ,9600bps:270 void
发表于 2020-03-23
STM8 普通IO配置模拟串口输出
STM8 I口模拟串口通信
使用普通的IO口,模拟串口协议, 和PC端串口调试软件实现通信。网上找了很多资料,有很多网友有些程序,但是感觉都不是很完整,无意间看到ST官方居然有实现,直接下载代码开始用。针对官方的IO口模拟串口软件,简单介绍下用到资源。由于模拟的串口RX脚,对于电平的输入判断用到定时器的输入捕获功能,所以官方用的是定时器3的通道2。我自己在STM8S003F3P6最小系统上,移植到了TIM2的CH1即PD4用来做串口的RX脚,和PC端串口调试器的TX脚连接。模拟串口的TX脚没有特殊要求,我这里用的PD3。。。。修改了MAIN里面的函数,实现模拟串口直接发送接收到的数据。PPS,关于串口波特率的配置,这个软件包你需要配置下使用外部24MHZ
发表于 2020-03-23
PIC16模拟串口以及采样正弦波
最近两周用了两个IC(PIC16系列与STM8S系列)做了个产品,首次接触,遇到些问题,总结如下:1:PIC16模拟串口发送数据,一定要在中断服务函数中执行static void interrupt SystemISR(void){if(TMR0IE && TMR0IF)                   //32MHz  104us{  if(txCount) //检测数据是否发送完毕  {    TXD=(txData&0x01); //输出数据
发表于 2020-03-15
STM8S003F使用I/O口模拟串口(一)发送数据
最近在使用STM8S003F模拟串口发送数据,网上资源很多,但是没有找到我需要的,因此自己写一篇文章,做一个总结,这篇文章主要是不用库函数实现发送简单的过程。1、串口通信原理和模拟串口发送数据的原理标准串口数据格式为:起始位(1bit)+数据位(8bit)+校验位(1bit)+停止位(1bit)。其中起始位为低电平,停止位为高电平。串口通讯需要设置波特率和检查COM口。思路是这样的,我们使用定时器TIM2来定时,每隔一端时间发送一个位,从而实现模拟串口发送数据。2、获得定时器ARR自动装载的值为了简便,我们不要校验位,因此共有10个位的数据。我以stm8中9600bit/s的波特率计算的过程为例(1秒钟传输9600位)。可以计算出
发表于 2020-02-24
stm8l低功耗系列
最近干刚做了一个stm8的项目用的是L低功耗系列,其中遇到一个问题。外设寄存器的值怎么都写入不进去。用IAR仿真产看寄存器的值,不论写进去多少,都是初始值。后来把所有寄存器都写了一遍,发现有的能写进去,有的写不进去。比如GPIO的寄存器就能写进去。百思不得姐,偶然查看clock的库函数发现个函数是设置外设时钟的。这个系列,亦或者整个低功耗系列的每个外设是不是都需要在时钟寄存器中单独设置时钟。(以前所使用的芯片都是在外设寄存器中使能或者是禁使能)
发表于 2020-03-09
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved