我正在尝试使用SPI通信读取ADC(ADS8320)值。我正在为ARM和SM470R1B1控制器使用IAR嵌入式工作台。在数据表中,它表示前6位是虚拟读取,接下来的16位是actval数据。我试图读取24位并忽略前6位和后2位。当我尝试使用以下代码时,我得到错误的值。
unsigned int readADC8320(void)
{
value = AD8320_16(0xFFFFFF); // read registe
return value;
}
unsigned int AD8320_16(unsigned int value)
{
unsigned int data;
AD8320_CS_Status(0);
SW_Delay(DELAY_10US);
while(GIODOUTA&X2);
data = spi2(value >> 16); //read high 8 bits
data = (data << 6)| spi2(value >> 8); //read next 8 bits but 6+8 =14
data = (data << 8)| spi2(value >> 2); //add last two bits only
SW_Delay(DELAY_10US);
AD8320_CS_Status(1);
return data;
}
unsigned char spi2(unsigned char data)
{
// Write byte to SPI2DAT1 register
SPI2DAT1 = data;
while(!(SPI2CTRL3 & 0x01)){} // Wait for RxFlag to get set
return (SPI2BUF & 0x000000FF); // Read SPIBUF
}
任何人都可以建议我在哪里做错了。轮班操作我很穷。
答案 0 :(得分:2)
您的代码看起来很糟糕。例如,value
有什么用途?
您链接的数据表表明22个时钟周期就足够了(并且24个时钟周期都可以),假设SPI时钟在限制范围内(我认为最多2.4 MHz),则不需要额外的延迟。所以,我希望您的代码看起来更像
void AD8320_setup(void)
{
/* TODO:
* - Set SPI2 clock frequency, if programmable (max. 2.4 MHz)
* - Set SPI2 transfer size, if programmable (8 bits per byte)
* - Set SPI2 to latch data on the falling edge of clock pulse
* - Set SPI2 to pull clock high when inactive
* - Set AD8320 chip select pin as an output
* - Set AD8320 chip select pin high (it is active low)
* - Ensure AD8320 is powered
*/
}
uint16_t AD8320_16(void)
{
uint16_t result;
/* TODO: Set AD8320 chip select pin 0/LOW (to select it)
*/
/* TODO: Clear SPI2 FIFO if it has one,
* so that we get actual wire data,
* not old cached data.
*/
result = ((uint16_t)(spi2_read() & 3U)) << 14;
result |= ((uint16_t)spi2_read()) << 6;
result |= ((uint16_t)spi2_read()) >> 2;
/* TODO: Set AD8320 chip select pin 1/HIGH (to deselect it)
*/
return result;
}
spi2_read
的原型通常为unsigned char spi2_read(void);
,但它可能是任何整数类型,可以正确表示所有8位值(0到255,包括0和255)。在上面,我转换结果 - 在将任何不相关的位(如果有的话)用二进制AND操作掩盖到uint16_t
之后再转换到结果中的正确位置,这样无论{{1返回类型,我们可以用它来构造我们的16位值。
第一个spi2_read()
读取前8位。我假设您的设备SPI总线首先发送并接收最高有效位;这意味着6个虚位是最高有效位,2个最低有效位是结果的最高有效位。这就是为什么我们只保留第一个字节的两个最低有效位,然后将其转移14个位置 - 这样我们就可以将它们放在最重要的位置。
第二个spi2_read()
读取接下来的8位。这些是数据的第13..6位;这就是为什么我们将这个字节左移6个位置,并将OR与现有数据相对应。
最后spi2_read()
读取接下来的8位。最后两位将被丢弃,因为只有第一个(最重要的)6位包含我们感兴趣的其余数据。因此,我们将其向下移动2位,并将OR与现有数据相关联。
准备spi2涉及字大小(8位),数据速率(如果可编程)等等。
AD8320的片选只是一个通用输出引脚,它只是低电平有效。这就是为什么它在数据表中被描述为^ CS / SHDN:芯片在低电平时被选中,在高电平时被关闭。
该芯片是微功率芯片,因此需要的电流小于2mA,因此您可以从许多微控制器的输出引脚上为其供电。如果你这样做,你还必须记住在spi2_read()
函数中使该引脚成为输出和1 /高。