### HAL ATTENTION __HAL_TIM_DISABLE(&htim4); __HAL_TIM_SET_COUNTER(&htim4,0); __HAL_TIM_DISABLE_IT(&htim4,TIM_IT_UPDATE); __HAL_TIM_CLEAR_IT(&htim4,TIM_IT_UPDATE); __HAL_TIM_CLEAR_IT __HAL_TIM_CLEAR_FLAG 区别 __HAL_TIM_CLEAR_FLAG对应了SR寄存器中的每一个标志位,多了 OC IC相关 而__HAL_TIM_CLEAR_IT仅对应了几种伴随中断产生的标志位 真正使能/失能定时器中断的要对DIER寄存器进行操作,即为__HAL_TIM_ENABLE_IT和__HAL_TIM_DISABLE_IT __HAL_TIM_GET_IT_SOURCE则是通过DIER寄存器查询定时器中断是否使能 HAL_NVIC_ClearPendingIRQ(USART2_IRQn); HAL_TIM_Base_Start_IT(&htim5); //开启定时器5中断 HAL_TIM_Base_Start_IT(&htim6); //开启定时器6中断 HAL_TIM_IC_Start_IT(&htim5, TIM_CHANNEL_1); //启动输入捕获 主要用到的函数: HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) if(NULL == huart->hdmarx) { /* 如果为中断模式,恢复接收地址指针到初始化buffer位置 */ huart->pRxBuffPtr -= huart->RxXferSize; } if(huart->hdmarx->Init.Mode != DMA_CIRCULAR) ### DMA 想真正 半满地方 tail_ptr = (huart->RxXferSize >> 1) + (huart->RxXferSize & 1); //获得一半的位置,奇偶都可以 offset = uart_rt.head_ptr % huart->RxXferSize; // 求余数 ,不大于就是本身 copy = tail_ptr - offset; uart_rt.head_ptr += copy; // 设置指针位置 uart1_write_rx_fifo(huart->pRxBuffPtr + offset, copy); // 拷贝数据FIFO 全满地方 tail_ptr = huart->RxXferSize; // 如果不定长就得处理 offset = uart_rt.head_ptr % huart->RxXferSize; copy = tail_ptr - offset; uart_rt.head_ptr += copy; uart1_write_rx_fifo(huart->pRxBuffPtr + offset, copy); ### 拷贝buf //复制 memcpy(RxBLUETOOTH,RxBuf,RxBufSize); //清空接收缓存 memset(RxBuf,0,sizeof(RxBuf)); HAL_UART_Receive_IT(huart,correction_Table, datalength); //重新配置了从buffer开始接收等系列操作 HAL_UART_DMAStop(&huart1); // 停止DMA接收 UART_RX_STA = UART_RX_LEN - __HAL_DMA_GET_COUNTER(huart1.hdmarx); // 总数据量减去未接收到的数据量为已经接收到的数据量 UART_RX_BUF[UART_RX_STA] = 0; // 添加结束符 UART_RX_STA |= 0X8000; // 标记接收结束 ### 定时器 开启定时器中断 HAL_TIM_Base_Start_IT(mytim->tim); // 开启后一直运行 HAL_TIM_Base_Stop(mytim->tim); HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, &new_value); ### iic几种模式 void process_eeprom() { myeeprom = Eeprom_init(); Eeprom_SET_I2C(myeeprom, &hi2c1); Eeprom_SET_Device_Model(myeeprom, AT24C02); Eeprom_SET_Device_Addr(myeeprom, 0xA0 ); if (HAL_I2C_GetState(myeeprom->i2c) == HAL_I2C_STATE_READY){ log_i("i2c ready"); } HAL_I2C_Mem_Write_IT(myeeprom->i2c, myeeprom->dev_addr, 0, I2C_MEMADD_SIZE_8BIT, i2ctxbuf, 1); while(myeeprom->writeCplt == 0); // 中断回调改变这个值 HAL_Delay(20); myeeprom->readCplt = 0; HAL_I2C_Mem_Read_IT(myeeprom->i2c, myeeprom->dev_addr, 0, I2C_MEMADD_SIZE_8BIT, i2crxbuf, 1); while(myeeprom->readCplt == 0); // HAL_I2C_Mem_Write(myeeprom->i2c, myeeprom->dev_addr, 0, I2C_MEMADD_SIZE_8BIT, i2ctxbuf, 1, 10); // // HAL_I2C_Mem_Write(&hi2c1, 0xa0, addr, I2C_MEMADD_SIZE_8BIT, &addr, 1, 10); // HAL_Delay(10); // HAL_I2C_Mem_Read(myeeprom->i2c, myeeprom->dev_addr, 0, I2C_MEMADD_SIZE_8BIT, i2crxbuf, 1, 10); log_i(" data : 0x%02x\n" , i2crxbuf[0]); } 使用DMA模式前,需要对DMA进行配置,这种模式下,也是要使用一定的时间来进行等待I2C的操作(I2C进行设置地址及读数据前操作,接收数据的时候,直接使用DMA记录)。 也是需要设置一个标志,回调后改变标志,前端等待这个标志改变 **f103 i2c没有dma通道** // I2c 中断回调函数 void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) { myeeprom->readCplt = 1; } void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) { myeeprom->writeCplt = 1; } #### 存结构体 typedef struct { uint8_t buf[10]; uint8_t b; }base_t; base_t b = {{0x77,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x80,0x81,0x99},10 }; base_t c ; HAL_I2C_Mem_Write_IT(myeeprom->i2c, myeeprom->dev_addr, 0, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&b, sizeof(b)); while(myeeprom->writeCplt == 0); // 中断回调改变这个值 HAL_Delay(20); myeeprom->readCplt = 0; HAL_I2C_Mem_Read_IT(myeeprom->i2c, myeeprom->dev_addr, 0, I2C_MEMADD_SIZE_8BIT,(uint8_t *)&c, sizeof(b)); while(myeeprom->readCplt == 0); // __HAL_I2C_GENERATE_START log_i(" data : 0x%02x 0x%02x\n " , c.buf[0], c.b); ### 1. 为什么IIC写EEPROM多字节出现问题 写入字节耗时,建议每个字节之间留足够时间 特别中断发送,是首先返回状态,然后后台写,可能会导致问题 2. 为什么上电uart 发送00 可能串口复用-到串口初始化过程中的电平变化导致 复用后立即初始化? 如果初始化打开中断的时候设置的缓冲区与串口接收中设置的缓冲区不是同一个,则会出现上电(初始化)接收到第一个字节为0x00,但是之后都正常的情况。 3. 为什么发送少一个字节 清TC 标志位