SPI原理
SPI协议详解(图文并茂+超详细)
SPI超详细解析
【STM32笔记】HAL库中的SPI传输(可利用中断或DMA进行连续传输)
AD5421芯片了解
AD5421是一款集成器件,设计用于环路供电型4-20mA智能发射器应用。AD5421在单芯片内提供如下特性和功能:16位DAC和电流放大器,用于对环路电流进行数字控制;用于为整个发射器供电的稳压器;基准电压源;故障报警功能;灵活的SPI兼容型串行接口;增益和失调调整寄存器;以及其它特性和功能。
AD5421为四线制信号芯片,这四个信号线分别为MISO、MOSI、CS、SCLK,即主入从出、主出从入、片选、时钟。片选信号线在有的地方也称SS,其是由主设备控制的,用来确定从机且低电平有效。当编写程序时,通常采用GPIO模拟片选信号(人为拉低pin电平)。
在本文,需要利用AD5421实现写入和读取数据的功能,首先通过芯片手册可以看到,实现写入功能的第八位是0,读取是1。
数据格式为8位命令+16位数据(+8位CRC循环校验)
AD5421数据传输时序图如下图所示,当SYNC为低电平时有效,此时,当SCLK为下降沿时传输数据,当SYNC为高电平时,输入的数据会锁存。
HAL库配置及初始化
根据芯片手册配置引脚和SPI引脚模式参数,开启中断。
SPI的片选信号设置为GPIO_Output,低电平有效,传输速度Low
配置完成后,同I2C一样,会生成一个SPI 的句柄。
SPI_HandleTypeDef hspi2;
部分代码
通过AD5421实现SPI通信
以下是基于HAL库的SPI收发函数,主要用到HAL_SPI_Transmit
和HAL_SPI_Receive
这两个函数实现,这两个函数相对应的就是HAL_SPI_Transmit_IT
和HAL_SPI_Receive_IT
,这两个函数和前两个函数的差别就是,前者是在阻塞模式下发送和接收消息,而后者是利用中断在非阻塞的模式下发送接收消息,前两个函数无法连续发送或接收消息,而后两个函数可以连续发送或接收消息。除此以外,还有用DMA直接存储模式读写消息,使用示波器也可以看到相关波形,这里没有演示,可以查看文章开头的第三个链接,里面有对这几个函数比较详细的解释。HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_RESET);
就是之前一直在讲的软件片选,人为拉高置低电平,启动SPI收发数据。
//this spi's transmisson can not continuous transmission of data.start
int spi_transmit(uint8_t *tpdat,uint16_t tdsize)
{
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_RESET);
if(tpdat != NULL || tdsize > 0)
{
HAL_SPI_Transmit(&hspi2,tpdat,tdsize,0xFFFF);
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_SET);
delay_ms(10);
return 1;
}
else
{
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_SET);
return 0;
}
}
int spi_receive(uint8_t *rpdat,uint16_t rdsize)
{
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_RESET);
if(rpdat != NULL || rdsize > 0)
{
HAL_SPI_Receive(&hspi2,rpdat,rdsize,0xFFFF);
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_SET);
delay_ms(10);
return 1;
}
else
{
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_SET);
return 0;
}
}
//this spi's transmisson can not continuous transmission of data.end
AD5421的读写数据函数,输入移位寄存器为24位(如果需要对数据进行CRC纠错校验,则为32位,这里没用到)。
24/32位字宽的数据在串行时钟输入SCLK的控制下优先载入器件的MSB位,所以在wbuf[1]时需要把data右移八位。
输入移位寄存器由8位地址/命令字节、16位数据字和可选的8位CRC组成。
写序列开始于SYNC信号的下降沿,数据在SCLK下降沿通过SDIN数据线输入。在SYNC上升沿,24位数据被锁存,然后传输到相关的寄存器并执行规定的功能(DAC输出改变或工作模式改变)。
void ad5421_write(uint8_t wadd,uint16_t data)
{
uint8_t wbuf[3];
memset(wbuf,0,sizeof(wbuf));
wbuf[0]=wadd&0x7F;
wbuf[1]=data>>8;
wbuf[2]=data&0x00FF;
spi_transmit(wbuf,3);
}
uint16_t ad5421_read(uint8_t radd)
{
uint8_t rbuf[3];
uint8_t read[3];
memset(rbuf,0,sizeof(rbuf));
rbuf[0]=radd;
rbuf[1]=0;
rbuf[2]=0;
spi_transmit(rbuf,3);
rbuf[0]=0x09;
rbuf[1]=0;
rbuf[2]=0;
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_RESET);
// HAL_SPI_Transmit(&hspi2,rbuf,1,0xFFFF);
// HAL_SPI_Receive(&hspi2,rbuf,2,0xFFFF);
HAL_SPI_TransmitReceive(&hspi2,rbuf,read,3,0xFFFF);
HAL_GPIO_WritePin (SPI_CS_GPIO_Port,SPI_CS_Pin,GPIO_PIN_SET);
return (read[1]<<8)|(read[2]&0xFF);
}
在这里有一个函数HAL_SPI_TransmitReceive
这个函数是指在阻塞状态下发送或接收一段数据,该函数在文件stm32l4xx_hal_spi.c下。文章来源:https://www.toymoban.com/news/detail-770228.html
/**
* @brief Transmit and Receive an amount of data in blocking mode.
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
* the configuration information for SPI module.
* @param pTxData pointer to transmission data buffer
* @param pRxData pointer to reception data buffer
* @param Size amount of data to be sent and received
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,uint32_t Timeout);
遇到的问题
SPI和I2C的代码编写步骤相似,思路也比较相像,但由于SPI读写寄存器这个完成了有一段时间了,所以遇到了什么问题其实印象有点模糊了,如果想到什么再加吧。
后面在实现读芯片温度和读VLoop功能时有遇到过问题,下文再述。文章来源地址https://www.toymoban.com/news/detail-770228.html
到了这里,关于【STM32L496】使用HAL库实现SPI写入/读取数据(AD5421)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!