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[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使用方法有问题?有大佬能指点一下吗,万分感谢!
|
|