通过SPI读取22位

时间:2015-08-11 15:17:52

标签: c embedded bit-shift spi adc

我正在尝试使用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 
  }

任何人都可以建议我在哪里做错了。轮班操作我很穷。

1 个答案:

答案 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 /高。