1.生成代码前的准备及点亮led
配置:在新的工程建立之初的左边的第一个systrm core中的
(1)sys配置:Debug选择第二个Serial Wire(选上后可以使用仿真器下载)
(2)RCC配置:选择高速时钟
(3)配置系统时钟:在上方的Clock configuration将系统时钟配置为72mhz
然后选择好引脚然后将引脚的初始状态设置为高电平(熄灭的状态)即
然后是GPIO mode分为推挽和开漏输出
GPIO Pull-up/Pull-down(GPIO的上拉和下拉一般用于按键)
Maximum output speed(输出的速度一般用于通信协议)
最后需要为代码文件命名,然后就是选择编译软件(这里我用的是keil选“MDK-ARM V5”)
然后在第5步中将第一个打对钩(可以生成对应的.c和.h文件也就是模块化)
最后就可以生成代码了
2.STM32CubeMX中的一些常用的函数
-
GPIO初始化:
HAL_GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
GPIOx
:指定要配置的GPIO端口。GPIO_InitStruct
:指向包含所需配置参数的结构体。例如:GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
读取GPIO引脚电平:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
GPIOx
:指定要读取的GPIO端口。GPIO_Pin
:指定要读取的GPIO引脚。- 返回值:返回该引脚的电平状态(
GPIO_PIN_SET
或GPIO_PIN_RESET
)。
-
设置GPIO引脚电平:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
GPIOx
:指定要写入的GPIO端口。GPIO_Pin
:指定要写入的GPIO引脚。PinState
:指定要设置的电平状态(GPIO_PIN_SET
或GPIO_PIN_RESET
)。
-
翻转GPIO引脚电平:
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
GPIOx
:指定要翻转的GPIO端口。GPIO_Pin
:指定要翻转的GPIO引脚。
-
串口发送数据:
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
huart
:指向UART句柄的指针。pData
:指向要发送的数据缓冲区的指针。Size
:要发送的数据长度。Timeout
:超时时间(单位为毫秒)。- 返回值:如果成功发送,则返回
HAL_OK
;否则,返回错误代码。
-
延时:
void osDelay(uint32_t delay);
delay
:以毫秒为单位的延迟时间。
-
队列发送:
BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );
xQueue
:指向队列句柄的指针。pvItemToQueue
:指向要发送到队列的数据项的指针。xTicksToWait
:等待插入操作完成的滴答数(在FreeRTOS环境下)。- 返回值:如果成功发送,则返回
pdTRUE
;如果超时则返回pdFALSE
3.User Lable提高代码的重用性
当你因为种种原因需要更换你的引脚后,发现代码中需要修改的引脚太多了,这时候为了解决这一问题我们就可以使用用户标签
那么什么是User Lable,它可以作什么?它可以帮我们在main.h中生成define语句具体如下。
弄完用户标签后就可以生成代码了。然后将代码中的替换成main.h中的宏定义(建议在一个工程开始的时候就用宏定义这样如果后面需要更改引脚,就只需要在cubeMX中将之前的用户标签填入新定义的引脚中。)
4.串口通信
(1)知道引脚对应的功能
当知道哪个引脚是想要的功能时可以直接在图中勾选,然后在左边的界面中选择串口数,然后右边所选的引脚会变绿
(2)不知引脚对应的功能
这个时候我们就可以借用该软件自动配置,方法如下:
先选择所需的串口数,然后在模式中选择“Asynchronous”,这时它就会自动配置好(如果其中可用引脚被占用了,系统会自动选择其他具有同样功能的引脚,为我们标绿)
除此之外对串口的配置也在步骤二下面的方框中,可以直接设置波特率,奇偶校验位等。然后就可以生成代码了。
以下是一些串口对应的函数
在使用printf函数时需要引入头文件<stdio.h>并且在
/* USER CODE BEGIN 0*/和/* USER CODE END 0*/之间填入
int fputc(int ch,FILE *f)
{
uint8_t temp[1] = {ch};
HAL_UART_Transmit(&huart1,temp,1,2);
return ch;
}
改代码的作用是对printf重定向以便于我们在函数中任意的使用printf来进行一个窗口的输出。
这里我有一种喜欢的格式printf(“【\t + 文件名】+信息”);这样写的好处是当你的代码变复杂时你可以清楚的知道打印数据的地方和它所处的装态。
(3)条件编译
条件编译就是当你在开发的时候你可以打印一些状态以此来调试你的产品,但是当你的产品完成后你可以将不需要打印的东西不执行
代码编写如下首先在/* USER CODE BEGIN PD */和/* USER CODE END PD */之间编写一个这样的函数
#define Log 1
#if Log // 如果是“1”就会执行下方的函数反之则不会
函数
#endif
(4)打印一些奇奇怪怪的字
在网址:
https://patorjk.com/software/taag/
中配置好自己的文字然后在主函数中while上面打多行printf函数然后将生成的字符一行一行的复制进去
(5)可变参数宏
/* USER CODE BEGIN includes*/和/* USER CODE END includes*/之间填入头文件和
#define USER_MAIN_DEBUG
#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...)printf(format"\r\n",##__VA_ARGS__)
#define user_main_info(format, ...) printf("[main] info:" foemat "\r\n",##__VA_ARGS__)
#define user_main_debug(format, ...) printf("[main] debug:" foemat "\r\n",##__VA_ARGS__)
#define user_main_error(format, ...) printf("[main] error:" foemat "\r\n",##__VA_ARGS__)
#else
#define user_main_printf(foemat,...)
#define user_main_info(foemat,...)
#define user_main_debug(foemat,...)
#define user_main_error(foemat,...)
#endif
效果:当在下面使用user_main_printf(“stm32”);它会自动在里面添加\r\n
如果去掉#define USER_MAIN_DEBUG后就只会
user_main_printf(“stm32”);输出结果和普通的printf一样
5.注意事项
在编写代码的时候一定要将代码写到其对应的(Private includes 带有这个单词的地方下面的)
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
之间,否者当你再次使用cubeMX改变东西时不按这个规则写的代码会直接消失。
6.外部中断(测量PWM频率)
1.首先选择你需要作为中断的引脚设置为中断引脚
2.进入system view使能中断,将EXTI line 0 inter和PVD interrupt though EXTI line 16勾选上
3.对GPIO进行配置:选上升沿触发,下拉
4.然后在main.c中编写
/* USER CODE BEGIN PV */
int pwm_value = 0;
/* USER CODE END PV */
然后在/* USER CODE BEGIN 4 */和/* USER CODE END 4 */之间写入
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin ==GPIO_PIN_0)
{
pwm_value++;
}
}
最后在main中的while中写入
pwm_value = 0;
HAL_Delay(1000);
printf("pwm_value -> %d Hz" , pwm_value );//user_main_info("pwm_value -> %d Hz" , pwm_value );
可以使用后面的封装好的函数但是(可能会有报错)