打印
[AT32F403/403A]

AT32F403A使用全双工SPI做从机+DMA能发送数据,但是无法接收数据

[复制链接]
1634|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
AT32F403A做从机,接收来自Linux的SPI数据,配置为全双工
Linux的主机一直发送0x55,等待AT32F403A接收
配置SPI思路,定义了两个全局变量来给DMA使用
分别是SPI_Slave_Buffer_RxSPI_Slave_Buffer_Tx
还开启了dma_init_struct.loop_mode_enable = TRUE 让每次传输完后计数器重新到设置值
具体代码如下

#define SPI_Slave                   SPI1
#define SPI_Slave_CLK               CRM_SPI1_PERIPH_CLOCK
#define SPI_Slave_GPIO              GPIOA
#define SPI_Slave_GPIO_CLK          CRM_GPIOA_PERIPH_CLOCK
#define SPI_Slave_PIN_NSS           GPIO_PINS_4
#define SPI_Slave_PIN_SCK           GPIO_PINS_5
#define SPI_Slave_PIN_MISO          GPIO_PINS_6
#define SPI_Slave_PIN_MOSI          GPIO_PINS_7
#define SPI_Slave_DMA_CLK            CRM_DMA1_PERIPH_CLOCK
#define SPI_Slave_Rx_DMA_Channel     DMA1_CHANNEL2
#define SPI_Slave_Rx_DMA_FLAG        DMA1_FDT2_FLAG
#define SPI_Slave_Tx_DMA_Channel     DMA1_CHANNEL3
#define SPI_Slave_Tx_DMA_FLAG        DMA1_FDT3_FLAG  

uint8_t SPI_Slave_Buffer_Rx[CMD_LEN]={0};
uint8_t SPI_Slave_Buffer_Tx[CMD_LEN] ={0x47, 0xC3, 0x4F, 0xFF, 0x40, 0x1C, 0x3F, 0xFF,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x56, 0x78, 0x56, 0x78, 0x78, 0x56, 0x78, 0x56,
                0x40, 0x1C, 0x3F, 0xFF, 0x40, 0x1C, 0x3F, 0xFF,
                0x40, 0x1C, 0x3F, 0xFF, 0x40, 0x1C, 0x3F, 0xFF};

void spi_gpio_configuration(void)
{
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);

    /* configure slave pins SCK */
    gpio_init_struct.gpio_pins = SPI_Slave_PIN_SCK;
    gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init(SPI_Slave_GPIO, &gpio_init_struct);

    /* configure slave pin MISO*/
    gpio_init_struct.gpio_pins = SPI_Slave_PIN_MISO;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init(SPI_Slave_GPIO, &gpio_init_struct);

    /* configure slave pins MOSI*/
    gpio_init_struct.gpio_pins = SPI_Slave_PIN_MOSI;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init(SPI_Slave_GPIO, &gpio_init_struct);

    /* configure slave pin CS*/
    gpio_init_struct.gpio_pins = SPI_Slave_PIN_NSS;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init(GPIOD, &gpio_init_struct);
}

void spi_configuration(void)
{
    dma_init_type dma_init_struct;
    spi_init_type spi_init_struct;

    /* SPI_Slave_Tx_DMA_Channel configuration ---------------------------------------------*/
    dma_reset(SPI_Slave_Tx_DMA_Channel);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = CMD_LEN;
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_base_addr = (uint32_t)SPI_Slave_Buffer_Tx;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&SPI_Slave->dt;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = TRUE;
    dma_init(SPI_Slave_Tx_DMA_Channel, &dma_init_struct);

    /* SPI_Slave_Rx_DMA_Channel configuration ---------------------------------------------*/
    dma_reset(SPI_Slave_Rx_DMA_Channel);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = CMD_LEN;
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_base_addr = (uint32_t)SPI_Slave_Buffer_Rx;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t)&SPI_Slave->dt;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_VERY_HIGH;
    dma_init_struct.loop_mode_enable = TRUE;
    dma_init(SPI_Slave_Rx_DMA_Channel, &dma_init_struct);

    /* SPI_Slave configuration ------------------------------------------------------*/
    spi_default_para_init(&spi_init_struct);
    spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
    spi_init_struct.master_slave_mode = SPI_MODE_SLAVE;
    spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_2;
    spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
    spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
    spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
    spi_init_struct.clock_phase = SPI_CLOCK_PHASE_1EDGE;
    spi_init_struct.cs_mode_selection = SPI_CS_HARDWARE_MODE;
    spi_init(SPI_Slave, &spi_init_struct);

    /* Enable SPI_Slave Tx Rx request */
    spi_i2s_dma_transmitter_enable(SPI_Slave, TRUE);
    spi_i2s_dma_receiver_enable(SPI_Slave, TRUE);


  /* Enable SPI_Slave_Rx_DMA_Channel */
    dma_channel_enable(SPI_Slave_Rx_DMA_Channel, TRUE);
    /* Enable SPI_Slave_Tx_DMA_Channel */
    dma_channel_enable(SPI_Slave_Tx_DMA_Channel, TRUE);
   
       /* Enable SPI_Slave */
    spi_enable(SPI_Slave, TRUE);
}


void SPI_Init(void)
{
    spi_gpio_configuration();
    spi_configuration();
}

采用轮询方法,没有写DMA中断服务函数,在主程序里面一直查询FDTF标志位看是否数据传输完毕
传输完毕就清除DMA相关的所有标志位,想开启下一次传输
AT32F403A主程序代码如下
  int main(void)
{
  // 240M
  system_clock_config();
  // IRQ priority
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  // init board resources
  at32_board_init();
while (1)
  {
    //...省略无关代码...//

        // 如果SPI的DMA接收完了数据,准备开始处理
    if (dma_flag_get(SPI_Slave_Rx_DMA_FLAG) != RESET)
    {
      for(int i=0;i<132;i++)
      {printf("RX:%x\r\n",SPI_Slave_Buffer_Rx[i]);}
      
      // 清DMA标志位
      dma_flag_clear(SPI_Slave_Rx_DMA_FLAG|DMA1_GL2_FLAG|DMA1_HDT2_FLAG|DMA1_DTERR2_FLAG);
      dma_flag_clear(SPI_Slave_Tx_DMA_FLAG|DMA1_GL3_FLAG|DMA1_HDT3_FLAG|DMA1_DTERR3_FLAG);
      /* Enable SPI_Slave_Rx_DMA_Channel */
      dma_channel_enable(SPI_Slave_Rx_DMA_Channel, TRUE);
      /* Enable SPI_Slave_Tx_DMA_Channel */
      dma_channel_enable(SPI_Slave_Tx_DMA_Channel, TRUE);
    }
   
    delay_ms(10);
}
}

现象
打印出SPI_Slave_Buffer_Rx缓存区的数据,发现都是0xFF,但是主机linux一直在发送0x55

使用逻辑分析仪抓取数据发现SPI_Slave_Buffer_Tx能够发送给主机,但是主机发送的0x55没有接收到
使用逻辑分析仪抓取如下

怀疑是DMA使用方法有问题?有大佬能指点一下吗,万分感谢!

使用特权

评论回复
沙发
DylanMingan|  楼主 | 2022-10-21 22:59 | 只看该作者
仔细排查后,发现是硬件问题,芯片的SPI的MOSI脚虚焊了。。

使用特权

评论回复
板凳
timfordlare| | 2022-11-1 19:44 | 只看该作者
SPI通信,MISO接收不到数据?

使用特权

评论回复
地板
burgessmaggie| | 2022-11-1 20:05 | 只看该作者
spi的配置有问题吗              

使用特权

评论回复
5
pl202| | 2022-11-2 17:01 | 只看该作者
这个spi的地址是否正常呢?              

使用特权

评论回复
6
elsaflower| | 2022-11-2 17:29 | 只看该作者
进入在线调试试试看,先建立一个存放SPI数据的变量,看看有没有数据;还可以在DMA中断函数设置一个FLAG,如果进入中断置1否则为0;如果是0的话确实没有进中断,那要看看你的配置了

使用特权

评论回复
7
everyrobin| | 2022-11-2 18:11 | 只看该作者
使用示波器查看一下是否有数据呢              

使用特权

评论回复
8
belindagraham| | 2022-11-2 18:59 | 只看该作者
AT32F403A的 SPI 从机模式并没有只接收这种配置吧

使用特权

评论回复
9
abotomson| | 2022-11-2 19:57 | 只看该作者
SPI从机接收数据错误是怎么回事  

使用特权

评论回复
10
yorkbarney| | 2022-11-2 20:47 | 只看该作者
SPI1 仅使用发送功能,SPI2 仅使用接收功能,两者均使用 DMA。

使用特权

评论回复
11
gygp| | 2022-11-3 20:25 | 只看该作者
使用这两个函数时必须得同时使用,若是接收数据时只调用SPI_I2S_ReceiveData()函数,那么spi clk 是不会产生clk的,所以不会收到数据。

使用特权

评论回复
12
iyoum| | 2022-11-3 21:15 | 只看该作者
设置全双工SPI模式时,需要向发送寄存器里面写数据,这样才能正常全双工通讯。

使用特权

评论回复
13
10299823| | 2022-11-5 09:49 | 只看该作者
用不用 SPI 从机发送功能,都必须要配置发送。

使用特权

评论回复
14
lzmm| | 2022-11-5 10:51 | 只看该作者
这个使用中断接收不行吗              

使用特权

评论回复
15
deliahouse887| | 2022-11-5 11:47 | 只看该作者
对照AT32F403A使用全双工SPI做从机+DMA的例子再仔细看看吧!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝