使用普通的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模拟串口通信了。
主要是为了节约成本,加个硬件的串口,成本又加了。
点我下载源码
我也来分享我刚刚纯模拟的串口程序吧,已经调试成功,一次只能接收发送1字节数据,全双工
- [code]void TIM2_Init(void)
- {
- TIM2->ARRH = 0x02; //自动重装载的值 255
- TIM2->ARRL = 0x2c; //自动重装载的值 255
- TIM2->PSCR = 0x00; //不分频
- TIM2->EGR = 0x01; //手动产生一个更新事件,用于PSC生效 注意,是手动更新
- TIM2->IER = 0x01; //使能溢出中断
- TIM2->CR1 = 0x01; //启动定时器
-
- //中断处理函数在TIM2_UPD_OVF_BRK_IRQHandler
- }
- INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
- {
- UartSoft_Tim();
- TIM2_ClearITPendingBit(TIM2_IT_UPDATE);
- }
- /**
- ******************************************************************************
- * @File :UartSoft.c
- * @Author :BLF
- * @Email :zhcj66@163.com
- * @Version :V1.0.0
- * @FileNewDate :2017-09-27
- * @FileChangeDate :2017-09-27
- * @Brief :软件模拟3倍波特率全双工串口
- :定时器中断频率=波特率*3
- :stm8 定时器设定值=定时器频率/(1/(波特率*3))=定时器频率/波特率/3=16000000/9600/3=555.5=556
- :测试间隔1ms收发一个数据,同时收发多个数据会出错
- ******************************************************************************
- */
- #include "includes.h"
- #include "UartSoft.h"
- #define RXB_PORT GPIOD //工作状态指示LED
- #define RXB_PIN GPIO_PIN_4
- #define TXB_PORT GPIOD //工作状态指示LED
- #define TXB_PIN GPIO_PIN_2
- #define RXB GPIO_ReadInputPin(RXB_PORT,RXB_PIN) //define UART TX/RX port
- #define TXB(x) x==1?GPIO_WriteHigh(TXB_PORT,TXB_PIN):GPIO_WriteLow(TXB_PORT,TXB_PIN)
- typedef unsigned char BOOL;
- typedef unsigned char BYTE;
- BYTE TBUF,RBUF;
- BYTE TDAT,RDAT;
- BYTE TCNT,RCNT;
- BYTE TBIT,RBIT;
- BOOL TING,RING;
- BOOL TEND,REND;
- BYTE buf[16];
- void UartSoft_Init(void)
- {
- GPIO_Init(RXB_PORT,RXB_PIN,GPIO_MODE_IN_PU_NO_IT);
- GPIO_Init(TXB_PORT,TXB_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
- TING = 0;
- RING = 0;
- TEND = 1;
- REND = 0;
- TCNT = 0;
- RCNT = 0;
- TIM2_Init();
- }
- //读取串口手机
- //返回0 数据无效;返回1 数据有效
- //*s 当返回为1 *s数据有效
- //注:在车里程序需不停扫描数据,否则会丢数据
- unsigned char UartSoft_Getc(unsigned char *s)
- {
- unsigned char St=0;
- if (REND)
- {
- REND = 0;
- *s = RBUF;
- St = 1;
- }
- else { *s=0xFF; }
- return St;
- }
- //发送数据需间隔一定时间 否则出错
- void UartSoft_Putc(unsigned char s)
- {
- if (TEND)
- {
- TEND = 0;
- TBUF = s;
- TING = 1;
- }
- }
- //定时器中断读取程序
- void UartSoft_Tim(void)
- {
- if (RING)
- {
- if (--RCNT == 0)
- {
- RCNT = 3; //reset send baudrate counter
- if (--RBIT == 0)
- {
- RBUF = RDAT; //save the data to RBUF
- RING = 0; //stop receive
- REND = 1; //set receive completed flag
- UartSoft_Putc(RBUF);
- }
- else
- {
- RDAT >>= 1;
- if (RXB) RDAT |= 0x80; //shift RX data to RX buffer
- }
- }
- }
- else if (!RXB)
- {
- RING = 1; //set start receive flag
- RCNT = 4; //initial receive baudrate counter
- RBIT = 9; //initial receive bit number (8 data bits + 1 stop bit)
- }
- if (--TCNT == 0)
- {
- TCNT = 3; //reset send baudrate counter
- if (TING) //judge whether sending
- {
- if (TBIT == 0)
- {
- TXB(0); //send start bit
- TDAT = TBUF; //load data from TBUF to TDAT
- TBIT = 9; //initial send bit number (8 data bits + 1 stop bit)
- }
- else
- {
- // TDAT >>= 1; //shift data to CY
- if (--TBIT == 0)
- {
- TXB(1);
- TING = 0; //stop send
- TEND = 1; //set send completed flag
- }
- else
- {
- if(TDAT&0x01){ TXB(1); }
- else { TXB(0); }
- TDAT >>= 1;
- }
- }
- }
- }
- }
复制代码一周热门 更多>