我不了解SPI驱动程序中的一行代码

时间:2014-11-17 11:30:42

标签: c pointers casting spi

uint32_t data;

SPDR = ((uint8_t*) & data)[x];

我可以看到这一行的作用 - 它可以放在一个for循环中来读取" data"的每一个字节。进入SPDR,但我不太明白它是如何运作的。

4 个答案:

答案 0 :(得分:3)

让我们把它分成不同的部分:

  • &data为您指向data,类型为uint32_t *
  • (uint8_t*)uint32_t指针转换为指向uint8_t(或无符号字节数组)的指针
  • 索引采用“array”
  • 中的一个字节

如果将其置于循环中,则从四字节uint32_t值开始一次占用一个字节,并将其分配给SPDR

答案 1 :(得分:1)

正如StackOverflow的Tag Info所说

  

串行外设接口(SPI)是串行,同步,完整的   双工总线常用于嵌入式系统。它最常用   用于微控制器和外围硬件之间的通信   如记忆,移位寄存器,传感器,显示器等,但也可以   用于MCU到MCU的通信。

     

传输通常涉及一些给定字的两个移位寄存器   大小,例如八位,一位在主人中,一位在奴隶中;他们   连接在一起。数据通常最多移出   首先是有效位,同时将一个新的最低有效位移入   同一个登记册。在该寄存器被移出后,   主设备和从设备已交换寄存器值。然后是每个设备   获取该值并对其执行某些操作,例如将其写入   记忆。如果有更多数据要交换,移位寄存器是   装载了新数据[1]并重复该过程。传输可能   涉及任意数量的时钟周期。当没有更多数据时   发送后,主机停止切换其时钟。通常,它然后   取消选择奴隶。 传输通常包含8位字。一个   如果希望/需要,主设备可以发起多个这样的传输。   但是,其他字大小也很常见,例如16位字   触摸屏控制器或音频编解码器,如德克萨斯州的TSC2101   仪器;或许多数字到模拟或12位字   模数转换器。

SPDR = ((uint8_t*) & data)[x]; 

将导致uint32_t指针转换为指向uint8_t的指针 - 指向8位的指针。指针算法基于指针类型,数组子映射基于指针算法


C标准n1124 § 6.5.2.1/2数组下标

后缀表达式后跟方括号[]中的表达式是下标 指定数组对象的元素。下标运算符[]的定义 是E1 [E2]与(*((E1)+(E2)))相同。由于转换规则 应用于二进制+运算符,如果E1是一个数组对象(等效地,指向 数组对象的初始元素),E2是整数,E1 [E2]表示E2 E1的元素(从零开始计数)。


因此索引数组将移动一个关于sizeof(*指针)的指针,因此为1个字节。这样你就可以遍历32位的所有4个字节。

答案 2 :(得分:0)

data是4字节,(uint8_t*) & data正在将它转换为1字节值的指针x,你没有显示,正在索引到1字节数组价值观。

答案 3 :(得分:0)

我仍然遇到这个问题。请采取以下措施:

uint16_t EN_A_WrRd_OP16(uint8_t opcode,uint16_t write_data)
{
    uint16_t read_data;
    uint8_t i;

    EN_A_CS_Low();
    SPIC_DATA=opcode;
    while (!(SPIC_STATUS&SPI_IF_bm));
    for (i=0;i<2;i++)
    {
        SPIC_DATA=((uint8_t*)&write_data)[i];
        while (!(SPIC_STATUS&SPI_IF_bm));    
        ((uint8_t*)&read_data)[i]=SPIC_DATA;
    }
    EN_A_CS_High();
    return read_data;        
    }

绕过循环两次以读取SPIC_DATA,它读取0x34然后读取0x12。但是,在退出循环时,read_data包含0x0000! 如果我以“长”方式执行此操作并使用以下内容替换循环:

    SPIC_DATA=write_data;
    while (!(SPIC_STATUS&SPI_IF_bm));
    read_data=SPIC_DATA;
    SPIC_DATA=write_data>>8;
    while (!(SPIC_STATUS&SPI_IF_bm));
    read_data|=SPIC_DATA<<8;

它正常工作,即read_data返回值0x1234。