keil清晰度问题:
右击keil>属性>兼容性>更改高DPI设置:
keil连接st-link下载及调试程序:
安装st-link驱动, 配置keil并编译下载例程
STLINK驱动获取: https://docs.qq.com/doc/DT2hyS2ZjY21WQkZt,转载于使用STLINK烧录STM32教程_哔哩哔哩_bilibili
程序烧录不自动运行:
调试退出时卡死
仿真打了断点,点Debug退出,KEIL死机,提示:Encountered an improper argument-OpenEdv-开源电子网
程序串口printf打印字符串异常,无法接收到数据
创建工程时使用没有修改为AC5编译器导致:
推挽和开漏
推挽(Push-Pull Output):
输入高电平时,经过反向后,上方的P-MOS管导通,下方的N-MOS关闭,对外输出高电平
输入低电平时,经过反向后,N-MOS管导通,P-MOS关闭,对外输出低电平。
开漏(Open Drain Output):
开漏模式输出时,上方的P-MOS管完全不工作。对于stm32,开漏就是失能了P-MOS,这样,当相应位置1时,引脚实际上是处在了浮空的状态,而通过外接的上拉电阻,将其拉高。
输入低电平,则P-MOS管关闭,N-MOS管导通,使输出接地
输入高电平,则P-MOS管和N-MOS管都关闭,所以引脚既不输出高电平,也不输出低电平,为高阻态。正常使用时必须接上拉电阻
它具有“线与”的特性,也就是说,若有很多个开漏模式引脚连接到一起时,只有当所有引脚都输出高阻态,才由上拉电阻提供高电平,此高电平的电压为外部上拉电阻所接所接的电压。若其中一个引脚为低电平,那线路就相当于短路接地,使得整条线路都为低电平,0伏。
在STM32的应用中,推挽输出模式一般应用在输出电平为0和3.3伏而且需要高速切换开关状态的场合。除了必须使用开漏模式的场合,我们都习惯用推挽输出模式。
开漏模式一般应用在I2C、SMBUS通讯等需要“线与”功能的总线电路中,除此之外,还用在电平不匹配的场合,如需要输出5伏的高电平,就可以在外部接一个上拉电阻,上拉电源为5伏,并且把GPIO设置为开漏模式,当输出高阻态时,由上拉电阻和电源向外输出5伏的电平。
CubeMX和Java
windows10关闭java自动更新 (亲试有效)_windows安装java显示update-优快云博客
CubeMX安装后无法联网待解决;
替代方法:直接在官网下载固件包以及升级包,解压后使用升级包替换固件包内的重复文件即可。【经验分享】学习使用HAL库进行STM32软件开发 | 安装STM32cubeMX及STM32F4支持包 - STM32团队 ST意法半导体中文论坛
CubeMX生成项目:
CubeMX配置好后生成项目,添加第三方文件,编译报错找不到文件或者变量未定义。需要将对应的目录添加到工程里面:
UART配置失败
配置UART中断时例程与CubeMX生成的代码使用的变量名不一致,导致配置UART后HAL_UART_Receive_IT开启中断失败、触发后重新使能中断失败:
//UART_HandleTypeDef g_uart1_handle; /* 例程 UART句柄 */
UART_HandleTypeDef huart1; /* CubeMX UART句柄 */
配置UART错误位置:
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */
HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
}
回调函数配置UART错误位置:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART_UX) /* 如果是串口1 */
{
数据接收...
//重新打开中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);
}
}
窗口看门狗
可以防止程序运行过快(陷入快速喂狗死循环)或者过慢(卡死、跑飞)
HAL库封装层次
时钟初始化为例(代码由CubeMX生成)
/*主函数调用时钟配置函数*/
int main(void)
{
...
SystemClock_Config();
...
}
/*时钟配置函数设置结构体并调用HAL库的RCC配置函数*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
...
RCC_OscInitStruct.xxx = xxx; /*配置振荡器结构体*/
...
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) /*调用HAL库函数进行时钟配置*/
{
Error_Handler();
}
}
/*HAL库的RCC配置函数判断合法后调用具体寄存器的配置函数*/
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
{
...
/* 配置 HSE */
__HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
...
}
/*寄存器配置*/
#define __HAL_RCC_HSE_CONFIG(__STATE__) \
do{ \
if ((__STATE__) == RCC_HSE_ON) \
{ \
SET_BIT(RCC->CR, RCC_CR_HSEON); \
} \
... \
}while(0U)
ADC配置为例:
中文编码乱码
使用CubeMX生成的代码中打印中文报错:
../Core/Src/main.c(109): warning: #870-D: invalid multibyte character sequence
printf("\r\n杩欐槸鍟?:\r\n");
CubeMX的代码不使用GB2312格式保存,解决方法,在外部使用其他编辑器(如VS code)等打开并修改文件编码
后重新打开keil工程并编译,即可通过且无警告
位带操作
通过硬件方式将指定寄存器(位带区域)的每一位都映射到一个32位的地址空间(别名区域)的对应位上(地址0x2000 0000 的值为0x0000 0000 0000 0001,第0位映射到0x2200 0000中的第0位,即0x xxxx xxxx xxxx xxx1)。通过操作映射后的地址,即可修改源寄存器的对应位
特点:高效,适用于需要频繁修改寄存器位的场景
在映射过程中,虽然每个位有一个映射地址,但是它们并不会真正“浪费”内存。位带操作通常是通过硬件地址映射的方式实现的,不会实际占用额外的内存空间。只是在内存地址空间中映射一个虚拟的、看似“浪费”的地址范围。
//计算别名区域地址
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF)<<5) + (bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define GPIOA_ODR_Addr (GPIOA_BASE + 12) // GPIOA 输出数据寄存器(ODR)
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr, n) // 输出宏
PAout(11) = 1; // 设置 GPIOA 第 11 位为 1 (高电平)
stm32运行神经网络: