分享自己移植的STM8 IO口模拟串口 代码

2020-01-02 19:37发布

使用普通的IO口,模拟串口协议, 和PC端串口调试软件实现通信。
网上找了很多资料,有很多网友有写程序,但是感觉都不是很完整,无意间看到ST官方居然有实现,直接下载代码开始用。

针对官方的IO口模拟串口软件,简单介绍下用到资源。
由于模拟的串口RX脚,对于电平的输入判断用到定时器的输入捕获功能,所以官方用的是定时器3的通道2。
我自己在STM8S003F3P6最小系统上,移植到了TIM2的CH1即PD4用来做串口的RX脚,和PC端串口调试器的TX脚连接。
模拟串口的TX脚没有特殊要求,我这里用的PD3。。。。
修改了MAIN里面的函数,实现模拟串口直接发送接收到的数据。

PPS,关于串口波特率的配置,
这个软件包你需要配置下使用外部24MHZ还是内部16MHZ的晶振,我这里配置的内部16M,
然后在模拟串口初始化里面,按照需要配置的波特率,配置定时器的时基。
常用的函数注释里面已经有给你计算好,直接copy就好, 我这里用的16M,9600bsp,所以填的是注释里面给的833.

简单配置以后就可以实现IO模拟串口通信了。


主要是为了节约成本,加个硬件的串口,成本又加了。

点我下载源码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
39条回答
zhcj66
2020-01-07 00:52
本帖最后由 zhcj66 于 2017-9-28 10:38 编辑

我也来分享我刚刚纯模拟的串口程序吧,已经调试成功,一次只能接收发送1字节数据,全双工


  1. [code]void TIM2_Init(void)
  2. {
  3.     TIM2->ARRH = 0x02; //自动重装载的值 255
  4.     TIM2->ARRL = 0x2c; //自动重装载的值 255
  5.     TIM2->PSCR = 0x00; //不分频
  6.     TIM2->EGR  = 0x01; //手动产生一个更新事件,用于PSC生效       注意,是手动更新
  7.     TIM2->IER = 0x01; //使能溢出中断
  8.     TIM2->CR1 = 0x01; //启动定时器
  9.    
  10.     //中断处理函数在TIM2_UPD_OVF_BRK_IRQHandler
  11. }


  12. INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
  13. {
  14.     UartSoft_Tim();
  15.     TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
  16. }


  17. /**
  18.   ******************************************************************************
  19.   * @File           :UartSoft.c
  20.   * @Author         :BLF
  21.   * @Email          :zhcj66@163.com
  22.   * @Version        :V1.0.0
  23.   * @FileNewDate    :2017-09-27
  24.   * @FileChangeDate :2017-09-27
  25.   * @Brief          :软件模拟3倍波特率全双工串口
  26.                     :定时器中断频率=波特率*3
  27.                     :stm8 定时器设定值=定时器频率/(1/(波特率*3))=定时器频率/波特率/3=16000000/9600/3=555.5=556
  28.                     :测试间隔1ms收发一个数据,同时收发多个数据会出错
  29.   ******************************************************************************
  30.   */
  31. #include "includes.h"
  32. #include "UartSoft.h"


  33. #define RXB_PORT                GPIOD         //工作状态指示LED
  34. #define RXB_PIN                 GPIO_PIN_4
  35. #define TXB_PORT                GPIOD         //工作状态指示LED
  36. #define TXB_PIN                 GPIO_PIN_2


  37. #define RXB                     GPIO_ReadInputPin(RXB_PORT,RXB_PIN)                        //define UART TX/RX port
  38. #define TXB(x)                  x==1?GPIO_WriteHigh(TXB_PORT,TXB_PIN):GPIO_WriteLow(TXB_PORT,TXB_PIN)

  39. typedef unsigned char BOOL;
  40. typedef unsigned char BYTE;

  41. BYTE TBUF,RBUF;
  42. BYTE TDAT,RDAT;
  43. BYTE TCNT,RCNT;
  44. BYTE TBIT,RBIT;
  45. BOOL TING,RING;
  46. BOOL TEND,REND;


  47. BYTE buf[16];

  48. void UartSoft_Init(void)
  49. {
  50.     GPIO_Init(RXB_PORT,RXB_PIN,GPIO_MODE_IN_PU_NO_IT);
  51.     GPIO_Init(TXB_PORT,TXB_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
  52.     TING = 0;
  53.     RING = 0;
  54.     TEND = 1;
  55.     REND = 0;
  56.     TCNT = 0;
  57.     RCNT = 0;
  58.     TIM2_Init();
  59. }

  60. //读取串口手机
  61. //返回0 数据无效;返回1 数据有效
  62. //*s 当返回为1 *s数据有效
  63. //注:在车里程序需不停扫描数据,否则会丢数据
  64. unsigned char UartSoft_Getc(unsigned char *s)
  65. {
  66. unsigned char St=0;
  67.     if (REND)
  68.     {
  69.         REND = 0;
  70.         *s = RBUF;
  71.         St = 1;
  72.     }
  73.     else { *s=0xFF; }
  74.     return St;
  75. }

  76. //发送数据需间隔一定时间 否则出错
  77. void UartSoft_Putc(unsigned char s)
  78. {
  79.     if (TEND)
  80.     {
  81.         TEND = 0;
  82.         TBUF = s;
  83.         TING = 1;
  84.     }
  85. }

  86. //定时器中断读取程序
  87. void UartSoft_Tim(void)
  88. {
  89.     if (RING)
  90.     {
  91.         if (--RCNT == 0)
  92.         {
  93.             RCNT = 3;                   //reset send baudrate counter
  94.             if (--RBIT == 0)
  95.             {
  96.                 RBUF = RDAT;            //save the data to RBUF
  97.                 RING = 0;               //stop receive
  98.                 REND = 1;               //set receive completed flag
  99.                 UartSoft_Putc(RBUF);
  100.             }
  101.             else
  102.             {
  103.                 RDAT >>= 1;
  104.                 if (RXB) RDAT |= 0x80;  //shift RX data to RX buffer
  105.             }
  106.         }
  107.     }
  108.     else if (!RXB)
  109.     {
  110.         RING = 1;                       //set start receive flag
  111.         RCNT = 4;                       //initial receive baudrate counter
  112.         RBIT = 9;                       //initial receive bit number (8 data bits + 1 stop bit)
  113.     }

  114.     if (--TCNT == 0)
  115.     {
  116.         TCNT = 3;                       //reset send baudrate counter
  117.         if (TING)                       //judge whether sending
  118.         {
  119.             if (TBIT == 0)
  120.             {
  121.                 TXB(0);                //send start bit
  122.                 TDAT = TBUF;            //load data from TBUF to TDAT
  123.                 TBIT = 9;               //initial send bit number (8 data bits + 1 stop bit)
  124.             }
  125.             else
  126.             {
  127. //                TDAT >>= 1;             //shift data to CY
  128.                 if (--TBIT == 0)
  129.                 {
  130.                     TXB(1);
  131.                     TING = 0;           //stop send
  132.                     TEND = 1;           //set send completed flag
  133.                 }
  134.                 else
  135.                 {
  136.                     if(TDAT&0x01){  TXB(1); }
  137.                     else         {  TXB(0); }
  138.                     TDAT >>= 1;
  139.                 }
  140.             }
  141.         }
  142.     }
  143. }

复制代码

一周热门 更多>