环境
CUBE MX 6.10.9
Keil 5.39
编译环境通之前的“CUBE MX结合Keil5 c/c++ STMF412混合编译调试记录”
编译出现错误
keil5调试一直卡在BEAB BKPT 0XAB
问题现象:
keil5调试一直卡在BEAB BKPT 0XAB
解决方案:
printf重定义c++不能正确链接,参考"CUBE MX结合Keil5 c/c++ STMF412混合编译调试记录"-“printf重定义报错“章节。
串口1DMA接收数据和数据长度为0
问题描述:串口DMA中断数据全0,数据长度也为0
rx_len = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); //计算出数据长度
检查dma.c发现cube模型没有生成以下函数:
/* DMA interrupt init */
/* DMA1_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
/* DMA2_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
/* DMA2_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
/* DMA2_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
解决方案:原因不明,估计是哪个寄存器设置有问题。我先用单字节串口接收程序调通后再换回DMA接收,换回去后DMA可正常接收,串口参数、引脚配置没有变化。
除了CUBEMX生成的代码(未改过),我的代码如下:
//main.c
/* USER CODE BEGIN 2 */
myPCHuart = huart1;
Config_Serial_Init();
************************************************************
stm32f4xx_it.c
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
#if((!UART_SINGLE_BYTE_RECV) == 1)
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
#endif
myPcUSART_IRQHandler();
/* USER CODE END USART1_IRQn 1 */
}
**************************************************************
//自定义c文件串口接收函数
void myPcUSART_IRQHandler()
{
#if((!UART_SINGLE_BYTE_RECV) == 1)
#if (ADSB_IN)
/*当DMA正常使用时启用*/
// 定义变量
extern uint8_t uart1_rx_buffer[BUFFER_SIZE];//接收数组
uint8_t rx_len = 0; //接收到的数据长度
if (__HAL_UART_GET_FLAG(&myPCHuart,UART_FLAG_IDLE) != RESET)// 通过IDLE标志位判断接收是否结束
{
HAL_UART_DMAStop(&myPCHuart);
//int dmaLen = __HAL_DMA_GET_COUNTER(&myHdma_usart_rx);
rx_len = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&myHdma_usart_rx); //计算出数据长度
if(uart1_rx_buffer[0] == '!')
{
//Config_RecHandler(uart1_rx_buffer);
Config_RecHandler_String(uart1_rx_buffer); // DMA命令处理
}
else
{
RingBuffer_Write(&rx_buffer_ring,uart1_rx_buffer,rx_len);
}
#if(DEBUG_MSG)
//RingBuffer_Read(&rx_buffer_ring,uart1_rx_buffer,rx_len);
// 发送接收到的数据
//printf("USART1_Ring Received:%s\r\n",uart1_rx_buffer);//打印接收到的数据
memset(uart1_rx_buffer,0,rx_len);
HAL_UART_Transmit(&huart1, uart1_rx_buffer,rx_len,1000);//将收到的数据发送出去
#endif
__HAL_DMA_SET_COUNTER(&myHdma_usart_rx, BUFFER_SIZE);
HAL_UART_Receive_DMA(&myPCHuart,uart1_rx_buffer,BUFFER_SIZE);//开启DMA接收,方便下一次接收数据
__HAL_UART_CLEAR_IDLEFLAG(&myPCHuart);//清除标志位
}
#endif
#else
USART1->SR &= ~USART_SR_RXNE;
unsigned char ch = USART1->DR;
//RingBuffer_Byte_Write(&PCData_rx_ring,ch);
Config_RecHandler(ch);
#endif
}
EC11 knob旋钮编码器无法进入HAL_TIM_IC_CaptureCallback中断
问题描述:EC11采用定时器Encoder采样,CUBEMX生成代码后无法进入EC11 knob旋钮编码器无法进入HAL_TIM_IC_CaptureCallback中断
配置如下:
解决方案:按照上图配置NVIC(最后两张配置截图)
配置SSD1312 OLED显示屏
纯代码配置:
使用CUBEMX配置好相关引脚为OUT PUT(不用CUBE配置SPI)引脚(DC、RES、CS、SDA、SCL),其中CS为spi的NSS,SDA一般为spi的MOSI,SCL为spi的CLK脚。并在OLED头文件添加以下代码:
/*外设配置区 Start*/
//-----------------OLED端口定义----------------
#define OLED_SCLK_Clr() HAL_GPIO_WritePin(OLED_SCK_GPIO_Port,OLED_SCK_Pin,GPIO_PIN_RESET)//SCL 即SPI-CLK引脚
#define OLED_SCLK_Set() HAL_GPIO_WritePin(OLED_SCK_GPIO_Port,OLED_SCK_Pin,GPIO_PIN_SET)
#define OLED_SDIN_Clr() HAL_GPIO_WritePin(OLED_SDA_GPIO_Port,OLED_SDA_Pin,GPIO_PIN_RESET)//DIN 即SPI-MOSI引脚
#define OLED_SDIN_Set() HAL_GPIO_WritePin(OLED_SDA_GPIO_Port,OLED_SDA_Pin,GPIO_PIN_SET)
#define OLED_RES_Clr() HAL_GPIO_WritePin(OLED_RES_GPIO_Port,OLED_RES_Pin,GPIO_PIN_RESET)//RES
#define OLED_RES_Set() HAL_GPIO_WritePin(OLED_RES_GPIO_Port,OLED_RES_Pin,GPIO_PIN_SET)
#define OLED_DC_Clr() HAL_GPIO_WritePin(OLED_DC_GPIO_Port,OLED_DC_Pin,GPIO_PIN_RESET)//DC
#define OLED_DC_Set() HAL_GPIO_WritePin(OLED_DC_GPIO_Port,OLED_DC_Pin,GPIO_PIN_SET)
#define OLED_CS_Clr() HAL_GPIO_WritePin(OLED_CS_GPIO_Port,OLED_CS_Pin,GPIO_PIN_RESET)//CS 即SPI-NSS引脚
#define OLED_CS_Set() HAL_GPIO_WritePin(OLED_CS_GPIO_Port,OLED_CS_Pin,GPIO_PIN_SET)
/*外设配置区 Start*/
然后将oled_ssd13xx.h和oled_ssd13xx.c文件移植进去,此时可以点亮屏幕,加入knob_EC11_key.h和knob_EC11_key.c旋钮按键和oled_panel.c即可添加GUI交互显示业务。
HAL_Delay(10);导致程序卡死
原因:下面代码破坏了SysTick,调用后恢复即可
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004;
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
// 重新初始化SysTick定时器
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
程序中调用了下面函数
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
修改为:
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
// 重新初始化SysTick定时器
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
0.5微秒定时器中断问题
问题描述:理论上,180MHz的系统