从零开始CubeMX配置STM32搭载freeRTOS实现多路ADC
引言
上篇文章介绍了自己的嵌入式学习路线,嵌入式进阶指南以及必备知识学习路线,刚入门的朋友可以去看一下,这篇文章我将结合公司的项目,介绍一下如何利用Cubemx配置freeRTOS以及开启任务实现多路ADC读取电压。
自己写的另外两篇文章
从零开始Cubemx配置STM32搭载freeRTOS以及lwip实现tcp网络通信(二)
从零开始使用CubeMX配置STM32使用lwip实现httpd服务器(三)
CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机(四)
CubeMX配置freeRTOS
freeRTOS是一种适用于嵌入式系统的轻量级实时操作系统,CubeMX配置freeRTOS其实很简单,在Middleware中选择CMSIS_V2,就可以了。硬件用的是野火的F407开发板。

在这里解释一下CMSIS_V2,现代编程为了实现与底层的分离,大多数又进行了一层抽象,比如之前用的HAL层以及SCOKET编程,用了这些思想后,上层的程序员不再关心底层是如何实现的,而底层程序员只需要按照接口规范提供接口就可以,这样就实现了上下层的分离,方便代码的移植,CMSIS就是ARM Cortex™ 微控制器软件接口标准(CMSIS:Cortex Microcontroller Software Interface Standard) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层。
版本V1和V2有一些不同,我喜欢用新不用旧,因此就采取了V2版本,第二代比第一代的有些实现不一样,比如用osThreadNew代替了osThreadCreat。例如lwip中有这样一段代码。就是根据CMSIS的版本不同,使用不同的函数进行创建任务。同时我们也可以看到lwip为了能够匹配这些版本就创建线程这个函数又进行了封装,统一使用sys_thread_new()来代替
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
{
#if (osCMSIS < 0x20000U)
const osThreadDef_t os_thread_def = { (char *)name, (os_pthread)thread, (osPriority)prio, 0, stacksize};
return osThreadCreate(&os_thread_def, arg);
#else
const osThreadAttr_t attributes = {
.name = name,
.stack_size = stacksize,
.priority = (osPriority_t)prio,
};
return osThreadNew(thread, arg, &attributes);
#endif
}
在stmcubeMX中进行配置的时候,如果使用了freertos系统,生成代码的时候会有如下提示:

其意思就是,当使用了FreeRtos的时候,强烈建议HAL库使用除了Systick以外的时钟源。也就是说当不使用FreeRtos的时候,HAL使用的是systick作为时钟源,现在使用了rtos,不建议hal库和rtos一起使用systick作为时钟源。
我们先看一下rtos和HAL库使用systick作为时钟源的代码:
在文件stm32f1xx_it.c中,滴答定时器中断内容如下图所示,可以看到HAL库和rtos公用一个systick作为时钟源

这里我们使用TIM1作为HAL库的时钟源,点击生成代码时,上边的警告已经不再出现了。

这一部分主要参考了这位大神的文章
freeRTOS使用简介


freeRTOS和其他操作系统一样,也是开线程,不懂得推荐去看看我上一篇文章中推荐的操作系统课,有多线程知识以及线程同步,信号量等知识。想试验的直接在MX_FREERTOS_Init加个任务,实现打印
printTaskHandle = osThreadNew(printf_hello, NULL, &defaultTask_attributes);
void printf_hello(void *argument)
{
while(1)
{
printf("hello world!!!!!\n");
HAL_Delay(100);
}
}
CubeMX配置多路ADC读取电压
主要看的这篇大神的文章,这个大神讲的已经很详细了,配置我就不再讲了,贴一下自己写的代码吧。
void MX_ADC_Init(void)
{
while(1)
{
Calculate_ADC();
}
}
void Calculate_ADC(void)
{
uint16_t ad_res[2];
float v_PA3, v_PA4;
for(int i=0; i<2; i++)
{
HAL_ADC_Start(&hadc1); //开启ADC
HAL_ADC_PollForConversion(&hadc1,10); //轮询转换
ad_res[i] = HAL_ADC_GetValue(&hadc1);
}
v_PA3 = ad_res[0] * (3.3/4096);
printf("读取到的PA3电压是%0.2f\n",v_PA3);
v_PA4 = ad_res[1] * (3.3/4096);
printf("读取到的PA4电压是%0.2f\n",v_PA4);
osDelay(1000);
}
然后把MX_ADC_Init初始化函数加入到线程中。
void StartDefaultTask(void *argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN StartDefaultTask */
MX_ADC_Init();
httpd_init();
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}
这样就可以实现读取多路电压了。
结论
本人在这篇文章中讲述了如何使用CubeMX配置freeRTOS以及如何进行简单的使用,如果有读者看不懂的话推荐先把操作系统好好学一学。自己目前也只是使用到了一些简单的功能,复杂的比如队列,自己还没用到,等用到的时候再好好看看。
自己将在下一篇文章中详细介绍一下如何移植LWIP以及实现TCP编程,httpd服务器。
本文介绍了如何使用CubeMX配置FreeRTOS,并通过STM32的多路ADC读取电压。首先,解释了CMSIS_V2的作用,并展示了如何在CubeMX中启用FreeRTOS。接着,简述了FreeRTOS的基本使用,包括创建任务。然后,详细说明了配置ADC读取电压的步骤,以及如何将ADC初始化函数加入到FreeRTOS任务中。最后,给出了代码示例和结论,强调了学习操作系统基础知识的重要性。
&spm=1001.2101.3001.5002&articleId=121975230&d=1&t=3&u=6a7c73c208f44cba8da5d6eb11289ff2)
3714

被折叠的 条评论
为什么被折叠?



