对STM32 HAL库的一些思考(一)SPI通信的数据格式问题
2017-11-08 20:21
746 查看
众所周知,STM32是一款性价比比较高的ARM芯片,并且它拥有极为丰富的外设,方便实现大部分的功能。2014年,意法半导体公司推出HAL(Hardware Abstracted Library)和配套的STM32CubeMX,更是让STM32的开发变得易如反掌,使得繁复的初始化代码仅需简单配置即可完成,这是一次重大的变革。然而,HAL库中的某些功能的确让人摸不着头脑,比如我们今天的主角SPI。
可以看到,传入该函数的数据指针是八位的,但是在C语言中,指针的类型是不可以混用的,于是问题来了,如何充分利用这个16位的DR寄存器呢?
在解决这个问题之前,先看一小段C语言代码
这段代码展示了如何处理不同类型的指针,如果将
理解了这一点后,就能很方便的理解SPI的函数了,在该函数源码中,关于16bit发送的部分如下:
可以看到对DR寄存器赋值时,采用了类型转换的方式,保证从内存中取出的数据为16位。
如果需要使用SPI发送16位数据,可以按照下例:
通过双机通信或者将数据写入flash,可以看到数据是正确的,不过依然建议对Flash或者E2PROM,采取单字节读写方式,安全可控。
全文完
关于SPI
SPI是Motorola推出的一种通信接口,它具有很多优点,这里不赘述,但是在HAL中,使用这个模块对应的库函数并非易事,那么问题出在哪里呢?SPI发送16位数据的问题
根据参考手册,STM32的SPI拥有一个16位的数据寄存器,记为DR,但是我们看HAL库的函数,以轮询发送为例/** * @brief Transmit an amount of data in blocking mode. * @param hspi pointer to a SPI_HandleTypeDef structure that contains * the configuration information for SPI module. * @param pData pointer to data buffer * @param Size amount of data to be sent * @param Timeout Timeout duration * @retval HAL status */ HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
可以看到,传入该函数的数据指针是八位的,但是在C语言中,指针的类型是不可以混用的,于是问题来了,如何充分利用这个16位的DR寄存器呢?
在解决这个问题之前,先看一小段C语言代码
#include "stdio.h" #include "stdint.h" uint16_t re(uint8_t* p) { uint16_t i = *(uint16_t*)p; return (i); } int main(void) { uint16_t i = 0x1234; uint8_t* p = &i; printf_s("0x%x \r\n", re(p)); return (0); }
这段代码展示了如何处理不同类型的指针,如果将
uint16_t的指针强行解释为
uint8_t,则新指针的数据为原指针的低八位,不过此时原有数据在内存中存储没有发生变化,因此我们仍可以用原有指针取出数据;同时,这种转换在C语言中是不安全的行为,常常产生警告,然而这种转换如果作为表达式参数传入函数中,则是合法的,所以以上代码的输出为0x1234。
理解了这一点后,就能很方便的理解SPI的函数了,在该函数源码中,关于16bit发送的部分如下:
/* Transmit data in 16 Bit mode */ if(hspi->Init.DataSize == SPI_DATASIZE_16BIT) { if((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01)) { hspi->Instance->DR = *((uint16_t *)pData); pData += sizeof(uint16_t); hspi->TxXferCount--; } /* Transmit data in 16 Bit mode */ while (hspi->TxXferCount > 0U) { /* Wait until TXE flag is set to send data */ if(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) { hspi->Instance->DR = *((uint16_t *)pData); pData += sizeof(uint16_t); hspi->TxXferCount--; } else { /* Timeout management */ if((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick()-tickstart) >= Timeout))) { errorcode = HAL_TIMEOUT; goto error; } } } }
可以看到对DR寄存器赋值时,采用了类型转换的方式,保证从内存中取出的数据为16位。
如果需要使用SPI发送16位数据,可以按照下例:
int main(void) { uint16_t arr[]={...}; HAL_SPI_Transmit(&hspi1, (uint8_t* )arr, sizeof(arr), HAL_MAX_DELAY); }
通过双机通信或者将数据写入flash,可以看到数据是正确的,不过依然建议对Flash或者E2PROM,采取单字节读写方式,安全可控。
全文完
相关文章推荐
- DSP与STM32的SPI通信调试及浮点数据传输调试
- STM32的从机SPI接收数据错位问题
- 关于STM32与SD卡通信的一些思考与总结
- 一些基本的数据格式小问题
- STM32与FPGA通信写数据出错问题解决方法
- STM32与FPGA通信写数据出错问题解决方法
- 使用redis缓存数据需要注意的问题以及个人的一些思考和理解
- 工作中遇到的问题:百万条数据的查询、删除、修改效率提高的一些思考,解决方案(一)
- 工作中遇到的问题:百万条数据的查询、删除、修改效率提高的一些思考,解决方案(二)
- [ROS]一些传感器数据读取融合问题的思考
- Android手机蓝牙与单片机通信数据格式问题
- STM32与FPGA通信写数据出错问题解决方法
- 用JSON做数据传输格式中的一些问题总结
- 对STM32 HAL库的一些思考(二)__weak关键字和systick
- 使用redis缓存数据需要注意的问题以及个人的一些思考和理解
- 用JSON做数据传输格式中的一些问题总结
- 关于STM32与SD卡通信的一些思考与总结
- 针对stm32 DMA传输AD数据,在完成中断后如何复位的问题的思考
- ~ 使用redis缓存数据需要注意的问题以及个人的一些思考和理解
- stm32单片机数据传输的一些问题。