建站公司获客成本,优速网站建设优化seo,全球设计在线,wordpress免费中文一、串口 1.串口定义#xff0c;将串口相关寄存器的首地址强制转化为串口结构体#xff0c;方便通过结果体访问串口的寄存器
#define __IO volatile /*! Defines read / write permissions */
typedef struct
{__IO uint32_t SR; /*! US…一、串口 1.串口定义将串口相关寄存器的首地址强制转化为串口结构体方便通过结果体访问串口的寄存器
#define __IO volatile /*! Defines read / write permissions */
typedef struct
{__IO uint32_t SR; /*! USART Status register, Address offset: 0x00 */__IO uint32_t DR; /*! USART Data register, Address offset: 0x04 */__IO uint32_t BRR; /*! USART Baud rate register, Address offset: 0x08 */__IO uint32_t CR1; /*! USART Control register 1, Address offset: 0x0C */__IO uint32_t CR2; /*! USART Control register 2, Address offset: 0x10 */__IO uint32_t CR3; /*! USART Control register 3, Address offset: 0x14 */__IO uint32_t GTPR; /*! USART Guard time and prescaler register, Address offset: 0x18 */
} USART_TypeDef;#define PERIPH_BASE 0x40000000UL /*! Peripheral base address in the alias region */
#define APB1PERIPH_BASE PERIPH_BASE
#define USART3_BASE (APB1PERIPH_BASE 0x00004800UL)
#define USART3 ((USART_TypeDef *)USART3_BASE)2.若有奇偶校验位 16比特数据传输
/* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */
if ((husart-Init.WordLength USART_WORDLENGTH_9B) (husart-Init.Parity USART_PARITY_NONE))
{ptxdata8bits NULL;ptxdata16bits (const uint16_t *) pTxData;
}
else
{ptxdata8bits pTxData;ptxdata16bits NULL;
}3.采样频率是波特率的16倍起始位将采样位置定位到一位的中间 4.串口有一个字节的缓冲 现象 串口助手连续发送receivedabc 打印数据为
9 received
10 areceived
10 areceived
10 areceived
10 areceived解释 从框图得知只看接收部分结构 数据先进入接收移位寄存器再进入接受数据寄存器 串口助手第一次发送receivedabc程序读取到停止即读到received后停止但是a进入串口接收移位寄存器等接收数据寄存器读空接收移位寄存器数据将移入接收数据寄存器因此第二次读取数据时从接收数据寄存器读取到的是字符’a’后续读取received也就是说第二次开始读取的是areceived。 while (1){rec_len get_usart_line(rx_buf, rx_max_size, 500000);rx_buf[rec_len] \0;if(rec_len 0) {char str[100];rec_len snprintf(str, sizeof(str) / sizeof(str[0]), %d %s\r\n, rec_len, rx_buf);HAL_UART_Transmit_DMA(huart6, (uint8_t *)str, rec_len);// HAL_UART_Transmit_DMA(huart6, rx_buf, rec_len);len rec_len;}rx_buf[0] 0;/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}int get_usart_line(uint8_t *rx, int rx_max_size, int timeout) {int t 0, i;uint8_t rx_buf 0;for(i 0; rx_buf ! t timeout i rx_max_size; t) {if(HAL_UART_Receive(huart6, rx_buf, 1, 0) HAL_OK) {// if(HAL_UART_Receive_DMA(huart6, rx_buf, 1) HAL_OK) {rx[i] rx_buf;}}return t timeout ? -1 : i;
}二、定时器 1.允许定时器中断
HAL_TIM_Base_Start_IT(htim2);2.重写定时器回调函数 函数原型
/*** brief Period elapsed callback in non-blocking mode* param htim TIM handle* retval None*/
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{/* Prevent unused argument(s) compilation warning */UNUSED(htim);/* NOTE : This function should not be modified, when the callback is needed,the HAL_TIM_PeriodElapsedCallback could be implemented in the user file*/
}重写
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim-Instance TIM2) {static int cnt 0;if(cnt 500) led_on();else if(cnt 1000) led_off();else cnt 0;cnt;}
}三、DMA 1.触发方式 硬件触发UART、ADC、IIC等外设设备 软件触发M2M置1内部触发尽快连续触发传输计数器快速转运数据不能喝自动重装一起使用否则会无限转运。 2.开关控制 当没有开启自动重装计数器清零时需要先关闭DMA重新填充初值再开启DMA注意必须先关闭 3.DMA通道 每个通道连接的外设不同必须选择对应外设的通道才能转运例如STM32F427IIH DMAUART6 RX必须选择DMA2通道1或通道2 TX必须选择通道DMA2的通道6或7。
四、SPI协议 1.硬件电路 特点输出引脚始终输出输入引脚始终输入主机MISO输出从机MISO输入。 引脚模式输出配置为推挽输出输入为浮空或则上拉。 从机所有从机输出默认高阻态否则可能造成短路例如从机1默认低电平从机2获得控制器权发送高电平将导致短路。 2.移位模型 一个时钟周期的一个边沿主机和从机移位寄存器同时左移一位根据移出的那一位将信号线置高或者拉低另一个边沿主机和从机同时从信号线将电平读入并将电平放入移位寄存器的最低位之后移位寄存器左移一位。 左边为最高位SPI是高位先行 3.传输模式 按scl空闲时状态CPOL控制输入和输出时机CPHA控制分四种模式 模式0scl空闲低电平第一个边沿读入第二个边沿输出 模式1scl空闲低电平第一个边沿输出第二个边沿读入 模式2scl空闲高电平第一个边沿读入第二个边沿输出 模式3scl空闲高电平第一个边沿输出第二个边沿读入 4.模式0时序 在SCK第一个边沿上升沿主机和从机从信号线读取最高位第二个边沿下降沿主机和从机将最高位移到信号线后续也是上升沿读取下降沿写入由于SCK第一个边沿就得读取因此在SS下降沿就应该先讲数据写入到数据线上。
5.全部模式时序四种模式的时序图分别为模式3 1 2 0 6.软件模拟spi读取mpu6500 协议时序核心代码
uint8_t swap_one_byte(uint8_t data) {/* 优化模拟移位寄存器从左边移出一位右边移入一位时序模式1空闲时scl为低电平第一个边沿读取数据即上升沿后立即读取数据下降沿后立即写入数据第一个数据是在ncss的下降沿发送*/for(int i 0; i 8; i) {mosi(data 0x80);data 1;scl(1);if(miso()) data | 0x01;scl(0);} return data;
}BUG记录 现象miso读取的电平始终为低电平 排查 1.烧录robomaster官方代码可正常读取排除硬件问题 2.排查代码GPIO配置、协议时序实现、GPIO读写接口 最后发现是GPIO读写接口错误具体如下 使用宏定义读写GPIO口但是GPIO口编号并不是1,2,3,4,5而是需要使用HAL库的宏GPIO_PIN_x
#define SPI_NCSS 6
#define SPI_SCL 7
#define SPI_MOSI 9
#define SPI_MISO 8
#define SPI_GPIO GPIOF修改后
#define SPI_NCSS GPIO_PIN_6
#define SPI_SCL GPIO_PIN_7
#define SPI_MOSI GPIO_PIN_9
#define SPI_MISO GPIO_PIN_8
#define SPI_GPIO GPIOF现象烧录后第一次读取mpu6500 id为0x00应为0x70 原因scl配置为默认高电平mpu6500采用模式0即第scl空闲时为0导致初始时mpu无法侦测到空闲位从而导致mpu无法正常读取到第一位数据。 应在0x75寄存器读取设备id拼接读写位后读写位拼接到最高位为0xf5由于上述原因mpu实际接受到的数据为0x75这意味着在0x75寄存器写入数据因此无法读取到0x75寄存器id为0是因为MISO默认电平为0 解决方案scl配置为默认低电平