10.找到STM32cubeMx所建的工程目录,在工程目录的同级目录下新建一个文件夹用来存放自己写的代码
11.用notepad++打开keil的工程文件,在这里的<Group>前面加上
<Group>
<GroupName>刚才新建的文件夹的名字</GroupName>
</Group>
这样用keil打开工程文件,就可以看到一个以新建的文件夹的名字命名的文件组了
12.添加一个userLogic.c文件
里面引出两个函数
void vUserInit(void);//放在main.c的大while前面,用于用户代码初始化,要把TIM6开启的代码放里面
!!!注意,里面开头一定要delay 2s,用于同步mcu与外围电路的上电时间,
避免不必要的麻烦
void vUserWhile(void);//放在main.c的大while里面,用来跑用户自定义的函数,
vUserWhile()函数里面的风格是这样的,timerFlgData是一个里面都是TIM6的时间Flg的结构体
if(timerFlgData.ucMainRunFlg==1)
{
vMainRun();
timerFlgData.ucMainRunFlg=0;
}
13.添加一个userTimer.c文件,里面就是初始化定时器(包括TIM6),各种定时器的回调函数(里面包括设置timerFlgData里的标志位的功能),以及延时函数
//By__Tuosheng-ml #include "userTimer.h" #include "tim.h" const uc fac_us=48;//时钟多少MHZ,就改多少 struct TimerFlgData timerFlgData; /*-----------------------------------------------------------*/ void vInitUserTimer(void) { HAL_TIM_Base_Start_IT(&htim6); } /*-----------------------------------------------------------*/ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//1ms { static ul prv_ulCnt=0; if(htim==&htim6) { if(!(prv_ulCnt% 20)) { timerFlgData.ucMainRunFlg=1; } } } /*-----------------------------------------------------------*/ void vDelay_us(ul nus) { ul ticks; ul told,tnow,tcnt=0; ul reload=SysTick->LOAD; ticks=nus*fac_us; told=SysTick->VAL; while(1) { tnow=SysTick->VAL; if(tnow!=told) { if(tnow<told)tcnt+=told-tnow; else tcnt+=reload-tnow+told; told=tnow; if(tcnt>=ticks)break; } } } /*-----------------------------------------------------------*/ void vDelay_ms(us nms) { ul i; for(i=0;i<nms;i++) vDelay_us(1000); } /*-----------------------------------------------------------*/
14.新建一个userUtility.c文件用于放通用的程序,包括串口的回调函数,和串口错误处理函数,其头文件放类型重定义
#include "userUtility.h" #include "uartDrive.h" #include "usart.h" void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { __HAL_UART_CLEAR_FLAG(huart,HAL_UART_GetError(huart)); } /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart == &huart1) { vUartxRecData(); } // else if(huart == &huart2) // { // // } // else if(huart == &huart3) // { // // } // else if(huart == &huart4) // { // // } }
#ifndef __USER_UTILITY_H #define __USER_UTITITY_H //头文件中的ifndef - define - endif 可以用#pragma once来代替哦,使代码更简洁,更方便修改 #include "stdint.h" #include "stm32f0xx_hal.h" typedef int32_t sl; typedef int16_t ss; typedef int8_t sc; typedef uint32_t ul; typedef uint16_t us; typedef uint8_t uc; #endif
15.最后新建一个doData.c文件 里面用于处理数据
头文件可以这样写(例如),好处是超过8位的数据通过匿名结构体分开,到时候通过串口发送什么的好处理
#pragma anon_unions __packed struct SensorData { uc ucPM25_AQI; uc ucHCHO_AQI; uc ucCO2_AQI; uc ucTVOC_AQI; uc ucAQI; __packed union { ss ssT; __packed struct { uc scT_L; uc scT_H; }; }; __packed union { us usH; __packed struct { uc ucH_L; uc ucH_H; }; }; __packed union { us usPM25; __packed struct { uc ucPM25_L; uc ucPM25_H; }; }; __packed union { us usHCHO; __packed struct { uc ucHCHO_L; uc ucHCHO_H; }; }; __packed union { us usCO2; __packed struct { uc ucCO2_L; uc ucCO2_H; }; }; __packed union { us usTVOC; __packed struct { uc ucTVOC_L; uc ucTVOC_H; }; }; }; extern struct SensorData sensorData;
16.以上大概就是我自己的风格,这样做的好处是,只有vUserInit();和vUserWhile();两个函数是被写在STM32CubeMX生成的代码中的,其他的代码均通过HAL库中德回调函数耦合在一起,方便维护和移植
17.另外到调试的时候注意,将Create HEX File勾上
还有debug中Setting的Reset and Run勾上(不勾上的话调试不会复位,让代码从头跑),写到这
突然想到不勾上这个对于排除bug的调试是不是有用的,不勾上这个直接调试,能不能看到出现bug时,
代码的运行情况,这个还真没用过。。。