AT32F403A使用全双工SPI做从机+DMA能发送数据,但是无法接收数据
AT32F403A做从机,接收来自Linux的SPI数据,配置为全双工Linux的主机一直发送0x55,等待AT32F403A接收
配置SPI思路,定义了两个全局变量来给DMA使用
分别是SPI_Slave_Buffer_Rx和SPI_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={0};
uint8_t SPI_Slave_Buffer_Tx ={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);}
// 清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使用方法有问题?有大佬能指点一下吗,万分感谢!
仔细排查后,发现是硬件问题,芯片的SPI的MOSI脚虚焊了。。 SPI通信,MISO接收不到数据? spi的配置有问题吗 这个spi的地址是否正常呢? 进入在线调试试试看,先建立一个存放SPI数据的变量,看看有没有数据;还可以在DMA中断函数设置一个FLAG,如果进入中断置1否则为0;如果是0的话确实没有进中断,那要看看你的配置了 使用示波器查看一下是否有数据呢 AT32F403A的 SPI 从机模式并没有只接收这种配置吧 SPI从机接收数据错误是怎么回事 SPI1 仅使用发送功能,SPI2 仅使用接收功能,两者均使用 DMA。 使用这两个函数时必须得同时使用,若是接收数据时只调用SPI_I2S_ReceiveData()函数,那么spi clk 是不会产生clk的,所以不会收到数据。 设置全双工SPI模式时,需要向发送寄存器里面写数据,这样才能正常全双工通讯。 用不用 SPI 从机发送功能,都必须要配置发送。 这个使用中断接收不行吗 对照AT32F403A使用全双工SPI做从机+DMA的例子再仔细看看吧!
页:
[1]