打印
[STM32WB]

【stm32WB55】外设快速入门

[复制链接]
3210|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
flycamelaaa|  楼主 | 2023-7-26 09:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
工程模板文件的如何进行初始化
从cubemx软件找到本地保存包的地址。
本视频中作者对于STM32CubeMX的态度,只用来负责外设的初始化配置,将配置完成确认可以运行的代码再复制进工程中,这感觉也是不错的。
  • 在文件浏览器中确定要移植的模板文件
    文件名称
    文件地址

    CMSIS文件Drivers文件夹下的Device和include
    HAL驱动库STM32WBxx_HAL_Driver文件夹下的inc和src
    工程模板文件\Projects\P-NUCLEO-WB55.Nucleo\Templates文件夹下的inc和src
  • 复制到自己新建的模板文件夹下面,确定的格式是这样的 建立三个文件夹,命名如下Libraries,Project,Source
    文件夹名称
    文件名称
    文件含义

    LibrariesCMSIS官方库的CMSIS
    LibrariesFWLIB官方库的HAL部分
    Project用于创建keil的地方
    SourceApp保留
    SourceDev保留
    SourceMain官方库的template
    SourcePackages保留
    注:
    • 官方库的HAL部分,ll库可以不保留,初学阶段很少用到。
    • 官方库的HAL部分,”...template“ 不保留,后续自己定义定时器的方法
    • 官方模板文件中的”system_stm32wbxx.c“在CMSIS中有一份重复的了,放在template或者CMSIS都可以说得过去,只保留一份即可。
  • 在keil中建立工程目录**
  • 注释,重新编译,0错误0警告,完成。
  • 替换掉main.h 加入新的system.h system.c 和 config.h 其中config.h的作用相当于新的main.h,包含所有用到的头文件,这样调试起来比较方便,system.h和system.c用来抽离main.c的代码,使main.c工程看起来更加清爽,模板文件中有main.c,xxx_it.c,xxx_msp_init.c文件用到了main.h头文件,把这些地方全都换成config.h,编译,完成。
  • 记得执行一次save all,否则可能要收获一次血的教训。


使用特权

评论回复
沙发
flycamelaaa|  楼主 | 2023-7-26 09:17 | 只看该作者
GPIO外设 点亮LED灯
在参考资料UM2435中,可以看到套件中stm32WB55-Nucleo的大致介绍,
板载有三颗LED灯珠,从原理图中可以看到,分别接在PB5、PB0、PB1中。
用STM32CubeMX工具初始化外设驱动。开发板选择wb55-nucleo选项。
官方的开发板,默认的配置方案中就已经有了LED的脚位配置。
在外设的时钟可以看到,CPU1(M4内核)的时钟最高只有64MHz.
选定一个空的文件夹方便管理生成代码,选择对应的编译工具链,生成.c和.h的文件等
生成代码,用keil编译工具链先编译一趟看看有没有错误。
用hal库的接口编写最简单的闪灯程序,
HAL_GPIO_WritePin(LD1_GPIO_Port,LD1_Pin,GPIO_PIN_SET);       HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_SET);       HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin,GPIO_PIN_SET);       HAL_Delay(500);       HAL_GPIO_WritePin(LD1_GPIO_Port,LD1_Pin,GPIO_PIN_RESET);       HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET);       HAL_GPIO_WritePin(LD3_GPIO_Port,LD3_Pin,GPIO_PIN_RESET);       HAL_Delay(500);
烧录,复位测试,程序能够正常工作。

使用特权

评论回复
板凳
flycamelaaa|  楼主 | 2023-7-26 09:18 | 只看该作者
USART外设实现printf功能
回到STM32CubeMX的配置界面,wb55-nucleo板子自带的usb串口连接在PB7和PB6上
串口外设和io口初始化由cubemx完成了,要实现一个printf功能用于后续程序调试,只需要实现fputc接口,重定向到串口上就行,
引入头文件
#include "stdio.h"
fputc实现
int fputc(int ch, FILE* file) {     HAL_UART_Transmit(&huart1,(uint8_t*) &ch,1,200);     return ch; } //main.c中做测试:       printf(" hello world uart1 config ok!\r\n");       HAL_Delay(1000);
keil编译器中,需要选择use MicroLIB选项,否则串口正常运行时不会有输出,只有在debug模式下,调试时才有串口打印。
实现完成后,使用串口可以看到输出,默认配置是数据位7位。
实现Rx接收中断功能
这里用的是标准库的实现思路简单验证。
STM32CubeMX的修改如下:
  • 在STM32CubeMx中使能USART1外设的global interrupt
  • 修改中断的优先级,位置是在SystemCore的NVIC,可以先设置组优先级,再设置抢占和子优先级,stm32的优先级越大数字越小。
  • 完成,重新生成代码。
在KeilMDK软件中,stm32主要在 HAL_UART_MspInit底层初始化的函数中新增了以下的代码:
/* USART1 interrupt Init */     HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);     HAL_NVIC_EnableIRQ(USART1_IRQn);
代码设置了优先级并且使能了串口的中断。
要实现串口的接收,我们主要需要修改串口中断服务函数,纯中断而且比较简单的实现是:使能两个标志位,RX空闲(IDLE)和RX非空(RXNE)标志位。
在外设数据寄存器非空标志位中,把数据从Rx外设搬运进数组。
在外设空闲标志位中,我们把数组的数据直接用printf打印出来。
  • 使能两个标志位,位置可以是在MX_USART1_UART_Init函数中,cubemx并不帮我们生成这两个标志位。
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
  • 在串口的中断服务函数USART1_IRQHandler中,实现rx数据接收和回显。
    uint8_t g_usart1_rxbuf[240]; // global uint8_t g_usart1_rxidx = 0; // global //... uint8_t receive_char; if((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)) {     __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);     HAL_UART_Receive(&huart1,&receive_char,1,200);     g_usart1_rxbuf[g_usart1_rxidx ++] = receive_char; } if(( __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET)) {     g_usart1_rxbuf[g_usart1_rxidx] = '\0';//c字符串的终止符号     printf("usart1 receive:%s\n",g_usart1_rxbuf);     g_usart1_rxidx = 0;     __HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_IDLE); }
  • 回显现象


裸机用定时器实现简单的任务框架
在很多人介绍RTOS的时候,会笼统的把裸机说成是必须要延时等待长时间任务的,以此来说明其分时高效,不浪费cpu资源的特点。
裸机实现这样的特点是可行的,核心就是用定时器的定时功能。例如按键扫描,完全是可以放在1ms中断中通过软件的计数值进行按键的消抖,长短按的识别等等。但是没有框架,纯靠堆代码,会导致各种计数值和标志位飘散在程序中,看的凌乱而且难以管理。框架的引入可以大大节省各种命名的烦恼,保证程序的可靠性。
这个任务框架有点RTOS的味道主要由****task**和**multiTimer**两个文件组成,其中multiTimer是一个底层实现,有点类似用软件实现IIC,实际用户程序不应该使用这个底层。multiTimer实现了一个定时器链表,时钟滴答计时器可以放在systick中自增,每个while循环,将轮询定时器的超时时间,定时时间到了,执行回调函数,并且自动更新下一个超时时间。**
如何使用?
  • 定义一个任务数组,这些任务统一一个时钟,如1ms,任务数组将在函数中进行初始化。
    #define TASK_TIMER_CNT  4   //任务定时器个数,增加任务时须修改该宏值 struct Timer task_timer[TASK_TIMER_CNT];
  • 声明回调函数
    void led0_task_timer_callback(void);//任务回调函数声明 void led1_task_timer_callback(void);//任务回调函数声明 void led2_task_timer_callback(void);//任务回调函数声明 void uart_task_timer_callback(void);//任务回调函数声明
  • 初始化定时器数组,其大小和任务数组相同且一一对应。
    task_timer_parameter task_timer_para[TASK_TIMER_CNT] =  {    /*{timeout_cb,       timeout(ms),    repeat(ms)}*/    {led0_task_timer_callback, 1000,         1000},    {led1_task_timer_callback, 500,          500},    {led2_task_timer_callback, 200,          200},      {uart_task_timer_callback, 1000,               1000},    /*{timeout_cb,       timeout(ms),    repeat(ms)}*/   };
  • 任务定时器回调函数实现
    void led0_task_timer_callback(void)//任务回调函数实现 {   led0_toggle(); } void led1_task_timer_callback(void)//任务回调函数实现 {   led1_toggle(); } void led2_task_timer_callback(void)//任务回调函数声明 {     led2_toggle(); } void uart_task_timer_callback(void) {     printf("hello world\r\n"); }
  • 任务初始化函数
    int task_init(void) {      uint8_t task_index;   for(task_index = 0;task_index < TASK_TIMER_CNT;task_index++)   {       timer_init(&task_timer[task_index],                task_timer_para[task_index].timeout_cb,                 task_timer_para[task_index].timeout,                task_timer_para[task_index].repeat);        timer_start(&task_timer[task_index]);   }   return 0; }
  • 任务正常循环调用
    int task_run(void) {   timer_loop();   return 0; }
要添加任务,仅需要修改任务数的宏,声明和定义一个新的函数,然后设定多少ms执行一次即可。
小结
主要用wb55实现了最基础的外设驱动和功能。wb55的外设驱动起来还是比较舒服的,没有碰到太多的坑。
由于不熟悉hal库,有参考一些视频资料, 本文的代码和思路很大部分参考的一位b站大佬:hezhijie157,视频地址: STM32-HAL库速讲**哔哩哔哩bilibili**
代码资料:链接:https://pan.baidu.com/s/1AnxLqKJnwHRSpT6cIMzV-A提取码:3mgo

使用特权

评论回复
地板
童雨竹| | 2023-12-29 08:10 | 只看该作者

引线长度就决定了其响应信号的波长

使用特权

评论回复
5
Wordsworth| | 2023-12-29 09:13 | 只看该作者

数字电压表(DVM)或仪器来测量效率

使用特权

评论回复
6
Clyde011| | 2023-12-29 10:16 | 只看该作者

靠近功率开关管或整流器的电容分到的纹波电流远多于相距较远的电容分到的纹波电流

使用特权

评论回复
7
公羊子丹| | 2023-12-29 11:09 | 只看该作者

任何一条PCB引线都可能成为天线

使用特权

评论回复
8
万图| | 2023-12-29 12:12 | 只看该作者

滤波电容、功率开关管或整流器、电感或变压器

使用特权

评论回复
9
Uriah| | 2023-12-29 13:15 | 只看该作者

离线式变换器

使用特权

评论回复
10
帛灿灿| | 2023-12-29 15:11 | 只看该作者

交流能量就会从输入或输出滤波电容上流进流出

使用特权

评论回复
11
Bblythe| | 2023-12-29 16:14 | 只看该作者

经变压器映射成这么多节点

使用特权

评论回复
12
周半梅| | 2023-12-29 18:10 | 只看该作者

专门的滤波器来阻止交流噪声进入周围的电路

使用特权

评论回复
13
Pulitzer| | 2023-12-29 19:13 | 只看该作者

电流型变换器电流检测电阻的公共接点和输出端电阻分压器的下端

使用特权

评论回复
14
Pulitzer| | 2023-12-29 19:13 | 只看该作者

电流型变换器电流检测电阻的公共接点和输出端电阻分压器的下端

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

648

主题

2689

帖子

0

粉丝