完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
文章目录
0 准备材料 1、需要正点原子的HAL介绍书籍可以翻阅 http://www.openedv.com/docs/boards/stm32/zdyz_stm32f103_mini.html 2、下载安装cubeMX,cubeMX是初始化代码生成器,能很快地生成硬件基础配置,基于HAL库。版本越新越好,我的是en.stm32cubemx_v6-0-0。 https://www.st.com/zh/development-tools/stm32cubemx.html 正常安装cubeMX后点击软件的这里添加包支持,我需要开发STM32F103C8T6。 3、需要keil ARM软件,用习惯了。 1 闪烁PC13的小灯 1.1 新建工程 1.2 找到芯片,开始配置。顺便一提,这里可以看到芯片的的特性、资源图、手册,真是不要太perfect。 1.3 熟悉配置界面 RCC时钟外部输入打开,实物板子的外部时钟有8MHZ和32768HZ,外部8MHZ可以使得时钟达到最高的72MHZ,没有外部8MHZ内部时钟最高能调到64MHZ。没有外部32768HZ,内部的RTC模块工作不正常。下图是打开了的。一些情况下,设置外部时钟输入这不是必须的。 一定要做的事情,设置debug方式,我用的STLINK 2线下载,SWDIO SWCLK下载,设置为这个。 配置PC13端口为输出。左键点击引脚设置即可。 时钟配置中有芯片时钟的详细配置,非常详细。我没开外部晶振输入,用的内部的,图里有颜色的就是线路,可见RTC没打开,内部40KHZ工作不工作无所谓。点击HCLK可以自己设置一个时钟,我设置为16MHZ。 工程名字写好后,创建代码。 直接打开。 加逻辑代码: HAL_Delay(1000);HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); 设置debug 下载后即可运行。 2 正点原子工程移植 注意点以及细节 cubeMX缺点就是没printf、没delay_us,而且实际开发需要一些传感器,自己去搞就是重复造轮子,所以需要正点原子的例子支持。 过程简单粗暴,RCC中打开2个外部时钟输入,打开SYS中debug(!!注意,如果关了调试端口后不然下次只能串口下载了,很烦人),SYS中使用sysTick,使能USART1(这样cubeMX能把h啥的HAL依赖加进来,后面就不用自己加了,比较舒服,cubeMX把这些初始化,我们一样可以在keil里把初始化删了,不影响骚操作。其他的资源同理,比如需要ADC1就cube里加了再说,后面不想要就自己keil里删除)。 得到的keil工程,直接把原子的下面6个文件复制到.CoreSrc(main.c也在这里)中。 keil中添加上c文件,会得到下面这样的结构。 在main.c中添加包含 #include "sys.h" #include "delay.h" #include "usart.h" 然后修改main(),删除UART初始化函数(声明、定义、调用都删除),删除时钟初始化函数(声明、定义、调用都删除),全部用原子的。 Stm32_Clock_Init( RCC_PLL_MUL9 ); /* 设置时钟,72M */ delay_init( 72 ); /* 初始化延时函数 */ uart_init( 115200 ); /* 初始化串口 */ 点编译会出现下面这结果,就是说重复定义了,因为开始的时候用了cubeMX生成了UART1的东西和院子的重复了。 Build target 'DDDDD' compiling main.c... linking... DDDDDDDDDD.axf: Error: L6200E: Symbol USART1_IRQHandler multiply defined (by stm32f1xx_it.o and usart.o). DDDDDDDDDD.axf: Error: L6200E: Symbol HAL_UART_MspInit multiply defined (by stm32f1xx_hal_msp.o and usart.o). Not enough information to list image symbols. Not enough information to list the image map. Finished: 2 information, 0 warning and 2 error messages. "DDDDDDDDDD.axf" - 2 Error(s), 0 Warning(s). Target not created. Build Time Elapsed: 00:00:01 打开.stm32f1xx_hal_msp.c找到void HAL_UART_MspInit(UART_HandleTypeDef* huart),然后可以直接把这个函数删除掉,或者像下图这样添加__weak关键字,keil发现有2处相同定义时优先用没带__weak关键字的定义,自然就用原子的定义了。 打开…/Core/Src/stm32f1xx_it.c,同样修饰一下定义void USART1_IRQHandler(void) 打开…/Core/Src/stm32f1xx_it.h去修饰一下声明__weak void USART1_IRQHandler(void);这个操作无所谓,声明而已,可以不修饰。 __weak void USART1_IRQHandler(void); 再次编译就不会有错了。 一些细节: 细节1:原子的CORE文件和cubeMX的CMSIS效果一样的。 图1 原子的CORE文件 cubeMX的CMSIS 细节2: stm32f1xx_it.c/stm32f1xx_it.h里面是中断服务函数的定义和声明,除了SysTick_Handler和USART1_IRQHandler,其他的基本都是单片机发生异常后进入中断就再也出不去了(死机),比如发生数值溢出,keil编译的时候是不可预知这种错误的,单片机靠这个机制让自己”死掉“。 void NMI_Handler(void); void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); __weak void USART1_IRQHandler(void); 细节3: stm32f1xx_hal_msp.c 文件,这文件是ST公司推出HAL的主要目的,弱化硬件配置难度,下面一段话引用自原子书籍。 MSP,全称为 MCU support package,关于怎么理解 MSP,我们后面在讲解程序运行流程的时细节4: 什么是回调函数? 参看https://blog.csdn.net/x1131230123/article/details/106507086,回调函数就是一个通过函数指针调用的函数:编写一个函数,另一个函数可以用这个函数当参数。 原子有另外的解释:STM32 不完全手册( ( H AL 库 版) Msp 回调函数执行过程解读 在 STM32 的 HAL 驱动中HAL_PPP_MspInit()作为回调,被 HAL_PPP_Init()函数所调用。当我们需要移植程序到 STM32F1平台的时候,我们只需要修改 HAL_PPP_MspInit 函数内容而不需要修改 HAL_PPP_Init 入口参数内容。 下面这个函数或许更应该称为Callback函数。但毋庸置疑的是,HAL实现都用句柄操作,大量用__weak修饰一些回调函数,用户需要自己编写逻辑实现而不用过多在意硬件底层。 void HAL_UART_RxCpltCallback( UART_HandleTypeDef *huart ) { if ( huart->Instance == USART1 ) /* 如果是串口1 */ { } } 3,EMWIN学习资料stm32cubef1STM32Cube_FW_F1_V1.0.0中打开Release_Notes。包里面资料一应俱全,我建议我自己反复翻阅一下,能够更快熟悉HAL库。 3 freeRTOS 用cubeMX肯定图谋freeRTOS,尽情玩起来。 有下面注意点: 1 单片机是单核的,freeRTOS是为了让其CPU充分利用,任务切换。 2 任务切换依靠freeRTOS里的任务就绪状态表执行,对就绪任务进行分优先级切换。 3 freeRTOS是可抢断的。 4 临界区代码是指关闭所有中断后执行的一段代码,执行完后记得打开全局中断,不然任务无法切换。 5 任务的状态与切换。 6 任务之间的通信依靠信号量、消息队列、消息邮箱等机制。 7 内存管理的一些事情。 8 内核裁剪的一些事情。 9 cubeMX把freeRTOS的方法再次封装了,在cmsis_os.c文件中。这使得程序更简单了。 https://www.keil.com/pack/doc/CMSIS/RTOS/html/usingOS.html https://www.keil.com/pack/doc/CMSIS/RTOS/html/functionOverview.html 3.1 LED KEY 串口1 的一个实验 用cubeMX打开RCC的2个外部时钟输入 打开PC13作为LED输出 打开PB7 PB6 PB5 PB4作为按键输入 打开SYS中的serial Wire,选择TIM1作为Timebase Source(避免和freeRTOS的心跳冲突) 打开USART1并打开中断 打开中间件FREERTOS并添加2个任务进去,LED和KEY任务。 在clock configuration中选择72MHZ时钟。 生成工程。 添加下面代码在main.c中使得串口1支持printf #include //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (unsigned char) ch; return ch; } 编写任务函数: /* USER CODE BEGIN Header_StartTask02 */ /** * @brief Function implementing the LED thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartTask02 */ void StartTask02(void const * argument) { /* USER CODE BEGIN StartTask02 */ /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);//取反 osDelay(1000);//延时1秒钟 } /* USER CODE END StartTask02 */ } /* USER CODE BEGIN Header_StartTask03 */ /** * @brief Function implementing the KEY thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartTask03 */ void StartTask03(void const * argument) { /* USER CODE BEGIN StartTask03 */ /* Infinite loop */ for(;;) { if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==0) { while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==0); printf(" press key1 rn"); } osDelay(10); } /* USER CODE END StartTask03 */ } 任务StartTask02每隔1000ms取反小灯,任务StartTask03每次PB7按键按下向串口发送数据。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1113 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1134 浏览 1 评论
569 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
424 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1020 浏览 2 评论
1610浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
275浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
288浏览 3评论
271浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
247浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-19 15:53 , Processed in 0.706274 second(s), Total 46, Slave 40 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号