STM32 freertos 使用软件模拟串口uart

如题,为什么要这样做?

最近做的一个项目上使用了74HC595作为指示灯板使用;

这个灯板与驱动板是通过排线连接,排线约25cm长;

在实验室测试一切正常,发到客户手上使用就出现了某个LED跳动情况;

跳动原因:传输线收到干扰。

这种显示方式抗干扰能力非常差且没有校验功能,满足不了需求;

因为传输线是必须要有的,所以只能通过增加校验的方式来处理干扰。

解决方法:

  1. 指示灯板增加MCU;
  2. 驱动板与灯板改为UART通讯增加校验功能;

因为驱动板与灯板连接的IO口没有UART外设功能,只能通过软件模拟UART使用;

代码

代码来自于:发个软件UART代码吧 (amobbs.com 阿莫电子技术论坛)

#include "SimComIO.h"
#include <string.h>//为了提高接收的准确率和纠错性能,采用3倍采样率,定时中断的频率是波特率的3倍。例如:需要波特率9600bps的话,需要1/(9600*3)=34.72us的定时中断。//#define SC_RXD 6
//#define SC_RXD_SET_INPUT() 	{DDRD&=(~BIT(SC_RXD));}
//#define SC_RXD_GET() 				((PIND&(BIT(SC_RXD))))
#define SC_RXD_GET() 				(HAL_GPIO_ReadPin(SIM_UART_RX_GPIO_Port, SIM_UART_RX_Pin))//#define SC_TXD 7
//#define SC_TXD_0() 					{PORTD&=(~BIT(SC_TXD));}
//#define SC_TXD_1() 					{PORTD|=BIT(SC_TXD);}
//#define SC_TXD_SET_OUTPUT() {DDRD|=BIT(SC_TXD);}
#define SC_TXD_0() 					{HAL_GPIO_WritePin(SIM_UART_TX_GPIO_Port, SIM_UART_TX_Pin, GPIO_PIN_RESET);}
#define SC_TXD_1() 					{HAL_GPIO_WritePin(SIM_UART_TX_GPIO_Port, SIM_UART_TX_Pin, GPIO_PIN_SET);}uint8_t sc1_rxd_scan_ct=0;
uint8_t sc1_rxd_scan_next_time=0;
uint8_t sc1_rxd_scan_step=0;
uint8_t sc1_rxd_dat;
uint8_t sc1_rxd_ready=0;
uint8_t sc1_rxd_tmpdat;volatile uint8_t sc_txd_ready=0;//模拟串口变量
volatile uint8_t sc_txd_bit_pt=0;
volatile uint8_t sc_txd_data=0;
volatile uint8_t sc_txd_ct=0;// typedef sim_uart_def{// uint8_t sc1_rxd_scan_ct;// uint8_t sc1_rxd_scan_next_time;// uint8_t sc1_rxd_scan_step;// uint8_t sc1_rxd_dat;// uint8_t sc1_rxd_ready;// uint8_t sc1_rxd_tmpdat;// uint8_t sc_txd_ready;//模拟串口变量// uint8_t sc_txd_bit_pt;// uint8_t sc_txd_data;// uint8_t sc_txd_ct;
// }TYPE_SIM_UART_DEF;// TYPE_SIM_UART_DEF su1,su2,su3,su4,su5,su6;// void SC_RxdSrv(TYPE_SIM_UART_DEF *pSU);
// void SC_TxdSrv(TYPE_SIM_UART_DEF *pSU);void SC_Recv_Pro(uint8_t dat){}void SC_RxdSrv(void){if(sc1_rxd_scan_step==0){if(!SC_RXD_GET()){sc1_rxd_scan_step=1;return;}}if(sc1_rxd_scan_step==1){if(!SC_RXD_GET()){sc1_rxd_scan_step=2;                //rxd start bit ok,goto next stepsc1_rxd_scan_ct=0;sc1_rxd_scan_next_time=3;sc1_rxd_tmpdat=0;return;}else{sc1_rxd_scan_step=0;        //rxd start bit is avalidreturn;}}if(sc1_rxd_scan_step>=2){sc1_rxd_scan_ct++;if(sc1_rxd_scan_ct<sc1_rxd_scan_next_time) return;sc1_rxd_scan_ct=0;if(sc1_rxd_scan_step<10){sc1_rxd_tmpdat>>=1;if(SC_RXD_GET()){sc1_rxd_tmpdat|=0x80;}sc1_rxd_scan_step++;       return;}if(sc1_rxd_scan_step==10){if(SC_RXD_GET()){sc1_rxd_dat=sc1_rxd_tmpdat;sc1_rxd_ready=1;//Receive a byte OK       #if 0sc_txd_data=sc1_rxd_dat;sc_txd_ready=1;#endif#if 0Test_Uart1(sc1_rxd_dat);#endifSC_Recv_Pro(sc1_rxd_dat);}sc1_rxd_scan_step=0;return;}}}void SC_TxdSrv(void){sc_txd_ct++;if(sc_txd_ct<3) return;sc_txd_ct=0;if(sc_txd_ready){                                                        //Data Readyif(sc_txd_bit_pt<10){if(sc_txd_bit_pt==0){SC_TXD_0();                                //Start BIT}else{if(sc_txd_bit_pt>=9){SC_TXD_1();                        //End BIT}else{                                                        //数据位if((sc_txd_data>>(sc_txd_bit_pt-1))&0x01){       SC_TXD_1();}else{SC_TXD_0();}}                       }}               if(sc_txd_bit_pt>10){               sc_txd_bit_pt=0;                        //发送完后延时两个时钟,复位各标志sc_txd_ready=0;               }else{sc_txd_bit_pt++;                        //位指针自加               }}}void SC_send_char(uint8_t b){sc_txd_data=b;sc_txd_ready=1;while(sc_txd_ready==1);}
void SC_send_str(uint8_t *str){while((*str)!=0){SC_send_char(*str);str++;}}void SC_send_arr(uint8_t *arr,uint8_t len){while(len--){SC_send_char(*arr);}
}void init_SimComIO(void){//	SC_TXD_SET_OUTPUT();SC_TXD_1();
//	SC_RXD_SET_INPUT();}// #pragma interrupt_handler ISR_T1:8
// void ISR_T1(void)
// {
// //compare occured TCNT1=OCR1A// SC_RxdSrv();// SC_TxdSrv();
// }

移植

定时器

        波特率9600,3倍采样34.72us,使用定时器2完成

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM4) {HAL_IncTick();}/* USER CODE BEGIN Callback 1 */if (htim->Instance == TIM2) {
//    HAL_GPIO_TogglePin(SIM_UART_TX_GPIO_Port, SIM_UART_TX_Pin);SC_TxdSrv();
//		SC_RxdSrv();}/* USER CODE END Callback 1 */
}

示波器观察IO引脚反转周期,符合需求。 

Freertos

HAL_TIM_Base_Start_IT(&htim2);    

在开启定时器的时候,整个任务调度接近瘫痪。

问题分析:

freertos心跳是1ms,35us这样频繁中断会影响调度的。

现在的问题是:freertos 能用35us这样的中断吗?如果能应该怎么用?

于是chatgpt开始对话,问题主要是问gpt freertos中这种35us 频繁中断应该怎么使用?

没有得到想要的答案;

网络上没得到答案就咨询身边大佬吧;

转义:

就是咱们这个发送也不是连续不断发送,实际使用中1S发送1帧就行了。

使用

taskENTER_CRITICAL();
//code
taskEXIT_CRITICAL(); 

    加入代码测试,发现问题:进入临界区之后定时器2中断不进了,被关了。

于是想,那就使用停止调度的呗

vTaskSuspendAll();         /* 开启调度锁 */    printf("任务vTaskLed1正在运行\r\n");   if(!xTaskResumeAll())      /* 关闭调度锁,如果需要任务切换,此函数返回pdTRUE,否则返回pdFALSE */{taskYIELD ();}    

测试还是不行。

二问大佬:

于是查代码,freertos在哪里管理中断的;

taskENTER_CRITICAL();

进这个接口查源码

最后查到了下面那个地方

打开cubemx 找修改优先级的地方

上面是修改优先级的地方,那定时器2的优先级是多少呢?

发现这个优先级是灰色的,是与freertos的 

是绑定的,比如你将 LIBRARY MAX SYSCALL INTERRUPT PRIORITY修改为6,定时器的优先级也会跟着修改为6;

那好办,在代码中手动修改定时器2优先级

HAL_NVIC_SetPriority(TIM2_IRQn, 4, 0);HAL_NVIC_GetPriority(TIM2_IRQn, TIM2_PriorityGroup, &TIM2_PreemptPriority, &TIM2_SubPriority);printf(" HAL_NVIC_GetPriority TIM2_PriorityGroup:%d, TIM2_PreemptPriority:%d,TIM2_SubPriority:%d  \r\n" ,TIM2_PriorityGroup,TIM2_PreemptPriority,TIM2_SubPriority);

验证修改成功。

验证

SC_send_char(0x55);

发现使用上面代码会卡在这个while里面,单步调试查看 sc_txd_ready 变量已经变为0了,为什么还会卡在这里? 

void SC_send_char(uint8_t b){sc_txd_data=b;sc_txd_ready=1;while(sc_txd_ready==1);}

解决方法

加入volatile 修饰符;

volatile uint8_t sc_txd_ready=0;

总结

        通过上面学习使用方法与故障排除,STM32 freertos 使用软件模拟串口uart已经正常可以使用了。通过这个测试也对freertos 有了进一步认识。

感谢

babyos 作者 提供的帮助;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/424504.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【6】密评中对服务端采用“挑战-响应”机制进行身份鉴别的验证

对服务端采用“挑战-响应”机制进行身份鉴别的验证 1、提取出服务端的签名值 签名值&#xff08;hex&#xff09;&#xff1a; 3045022100e4795b5a947526f8e7cbd0edd571ea8749e0efd24323799346ea2c740c006c5a0220026189e51c19d20d40a82606d0ed72cb9530a189bbb94c09e4559d7d8f…

人工智能 | 自然语言处理的发展历程

github&#xff1a;https://github.com/MichaelBeechan CSDN&#xff1a;https://blog.csdn.net/u011344545 自然语言处理的发展 方向一&#xff1a;技术进步1. 基于规则的语法&#xff08;1950-1990&#xff09;2. 统计语言处理&#xff08;1990-2010&#xff09;3. 基于深度学…

QSqlQuery 执行Update 判断执行成功与否

1.执行更新操作的SQL语句 update s_info set name"009" where contact_number "13511112222" 怎么样判断是否确实更新操作是执行成功的 &#xff0c;可以通过下列语句判断 query.numRowsAffected() > 0 2.主要的几步操作如下: QSqlQuery query;query.…

亿发中小型企业erp软件智能化赋能,专业助力广东制造行业生产流程管理

在当前经济全球化的环境下&#xff0c;广东省的中小型制造业企业正面临多方面的严峻挑战。包括产品质量的维护、分销渠道的稳定、生产成本降低以及减轻生产过程中的资源消耗等难题。目前&#xff0c;随着信息技术的迅速发展&#xff0c;一些先进的IT工具&#xff0c;比如企业资…

Android状态栏布局隐藏的方法

1.问题如下&#xff0c;安卓布局很不协调 2.先将ActionBar设置为NoActionBar 先打开styles.xml 3.使用工具类 package com.afison.newfault.utils;import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.graph…

【吃灰开发板复活】DIY全志V3s随身终端屏幕适配,LVGL以及各种外设驱动移植教程

在上周的文章中介绍了一款因作者想要学习Linux而动手DIY的终端设备V3S-PI&#xff0c; 《梦回2004&#xff01;我用全志V3s做了个成本100元&#xff0c;功能媲美MP4的随身终端》&#xff1a;梦回2004&#xff01;我用全志V3s做了个成本100元&#xff0c;功能媲美MP4的随身终端…

i18n多国语言Internationalization的动态实现

一、数据动态的更新 在上一篇i18n多国语言Internationalization的实现-CSDN博客&#xff0c;可能会遇到一个问题&#xff0c;我们在进行英文或中文切换时&#xff0c;并没有办法对当前的数据进行动态的更新。指的是什么意思呢&#xff1f;当前app.js当中一个组件内容&#xff…

AI对比:ChatGPT和文心一言的区别和差异

目录 一、ChatGPT和文心一言大模型的对比分析 1.1 二者训练的数据情况分析 1.2 训练大模型数据规模和参数对比 1.3 二者3.5版本大模型对比总结 二、ChatGPT和文心一言功能对比分析 2.1 二者产品提供的功能情况分析 2.2 测试一下各种功能的特性 2.2.1 文本创作能力 2.2…

webssh 通过web使用终端命令

简介&#xff1a;通过web就能使用终端命令 一、安装环境 # 安装webssh pip3 install webssh # 找到程序 find ~/anaconda3/envs/py37 -name webssh # 进入找到的目录 cd ~/anaconda3/envs/py37/lib/python3.7/site-packages/webssh/ # 开启服务 python main.py

架构篇08:架构设计三原则

文章目录 合适原则简单原则演化原则小结 成为架构师是每个程序员的梦想&#xff0c;但并不意味着把编程做好就能够自然而然地成为一个架构师&#xff0c;优秀程序员和架构师之间还有一个明显的鸿沟需要跨越&#xff0c;这个鸿沟就是“不确定性”。 对于编程来说&#xff0c;本…

FluoroQuest PLUS-抗淬灭封片剂,可以保护和增强荧光信号

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;FluoroQues tPLUS Antifade Mounting Medium&#xff0c;FluoroQues tPLUS-Antifade Mounting Medium&#xff0c;FluoroQuest PLUS 抗淬灭封片剂&#xff0c;FluoroQuest PLUS-抗淬灭封片剂 一、基本信息 产品简介…

架构篇10:架构设计流程-识别复杂度

文章目录 架构设计第 1 步&#xff1a;识别复杂度识别复杂度实战识别复杂度心得小结 从今天开始&#xff0c;我们分4期&#xff0c;结合复杂度来源和架构设计原则&#xff0c;通过一个模拟的设计场景“前浪微博”&#xff0c;一起看看在实践中究竟如何进行架构设计。今天先来看…