21ic问答首页 - GD32F303 SPI DMA 条件下如何配置8位的CRC
GD32F303 SPI DMA 条件下如何配置8位的CRC
chuancqc2024-08-08
如题 GD32F303 SPI DMA 条件下如何配置8位的CRC,我的配置如下
void Spi1_init()
{
spi_parameter_struct spi_init_struct;
/* deinitilize SPI and the parameters */
spi_i2s_deinit(SPI1);
spi_struct_para_init(&spi_init_struct);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_SPI1);
rcu_periph_clock_enable(RCU_AF);
/* configure SPI1 GPIO: NSS/PB12, SCK/PB13, MISO/PB14, MOSI/PB15 */
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13 | GPIO_PIN_15); /* SPI1 GPIO config: SCK/PB13, MOSI/PB15 */
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_14); /* SPI1 GPIO config: MISO/PB14 */
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); /* PB12 as CS */
SPI1_CS_H;
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.device_mode = SPI_MASTER;
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;// SPI 接口逻辑在时钟极性 (CPOL) = 0 和时钟相位 (CPHA) = 0 的情况下运行
spi_init_struct.nss = SPI_NSS_SOFT; //注意 SPI_NSS_HARD是指外部的CS 也就是说对从机有效 主机应该使用SPI_NSS_SOFT
spi_init_struct.prescale = SPI_PSC_32;
spi_init_struct.endian = SPI_ENDIAN_MSB;//大端
spi_init(SPI1,&spi_init_struct);
/* set crc polynomial */
spi_crc_polynomial_set(SPI1,7);
spi_crc_on(SPI1);
/* enable SPI1 */
spi_enable(SPI1);
}
我使用了,可是实际上示波器没有监测到下发的正常校验结果
spi_crc_polynomial_set(SPI1,7);
spi_crc_on(SPI1);
发送数据填充
{
Afex->Spi_Txbuf[0] = Afex->Aevaddr;
Afex->Spi_Txbuf[1] = 0xFF;
//Afex->Spi_Txbuf[2] = CRC8(Afex->Spi_Txbuf, 2);
AFE1_CS_L;
SPI1_TransmitReceiveDma(Afex->Spi_Txbuf, Afex->Afe_Rxbuf, 2);
AFE1_CS_H;
}
//DMA数据填充和发送使能等这里用了个信号量阻塞
uint8_t SPI1_TransmitReceiveDma(const uint8_t * data_tx, uint8_t * data_rx,const uint8_t length)
{
uint8_t result = 0;
taskENTER_CRITICAL();
dma_memory_address_config(DMA0,DMA_CH4,(uint32_t)data_tx);
dma_transfer_number_config(DMA0,DMA_CH4,length);
dma_memory_address_config(DMA0,DMA_CH3,(uint32_t)data_rx);
dma_transfer_number_config(DMA0,DMA_CH3,length+1);
spi_enable(SPI1);
dma_channel_enable(DMA0, DMA_CH4);
dma_channel_enable(DMA0, DMA_CH3); /* 使能 DMA 数据流 */
spi_dma_enable(SPI1, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI1, SPI_DMA_RECEIVE); /* 使能 SPI DMA 请求 */
taskEXIT_CRITICAL();
result = (xSemaphoreTake(spi1_txComplete, 50) == pdTRUE) &&
(xSemaphoreTake(spi1_rxComplete, 50) == pdTRUE); /* 等待传输完成 */
taskENTER_CRITICAL();
spi_disable(SPI1);
taskEXIT_CRITICAL();
return result;
}
//中断监测函数监测到发送或接收完毕后释放信号量接触发送现场阻塞
void spi1TxDmaIsr(void)
{
if(dma_interrupt_flag_get(DMA0,DMA_CH4,DMA_INT_FLAG_FTF)){
dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_G); /* 清除中断标志位 */
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
// dma_interrupt_disable(DMA0, DMA_CH4, DMA_INT_FTF);
dma_flag_clear(DMA0, DMA_CH4, DMA_FLAG_FTF); /*停止并清除 DMA 数据流 */
spi_dma_disable(SPI1, SPI_DMA_TRANSMIT); /* 关闭 SPI DMA 请求 */
dma_channel_disable(DMA0, DMA_CH4); /* 关闭数据流 */
xSemaphoreGiveFromISR(spi1_txComplete, &xHigherPriorityTaskWoken); /* 释放信号量 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
void spi1RxDmaIsr(void)
{
if(dma_interrupt_flag_get(DMA0,DMA_CH3,DMA_INT_FLAG_FTF)){
dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INT_FLAG_G); /* 清除中断标志位 */
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
// dma_interrupt_disable(DMA0, DMA_CH3, DMA_INT_FTF);
dma_flag_clear(DMA0, DMA_CH3, DMA_FLAG_FTF); /* 停止并清除 DMA 数据流 */
spi_dma_disable(SPI1, SPI_DMA_RECEIVE); /* 关闭 SPI DMA 请求 */
dma_channel_disable(DMA0, DMA_CH3); /* 关闭数据流 */
xSemaphoreGiveFromISR(spi1_rxComplete, &xHigherPriorityTaskWoken); /* 释放信号量 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
以上是SPI 驱动收发相关的配置,实际上并没有发出正确的校验值。
认为硬件crc会自动填充一位8bit数据到末尾的缓存区,官方文档对此说明很少。
void Spi1_init()
{
spi_parameter_struct spi_init_struct;
/* deinitilize SPI and the parameters */
spi_i2s_deinit(SPI1);
spi_struct_para_init(&spi_init_struct);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_SPI1);
rcu_periph_clock_enable(RCU_AF);
/* configure SPI1 GPIO: NSS/PB12, SCK/PB13, MISO/PB14, MOSI/PB15 */
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13 | GPIO_PIN_15); /* SPI1 GPIO config: SCK/PB13, MOSI/PB15 */
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_14); /* SPI1 GPIO config: MISO/PB14 */
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); /* PB12 as CS */
SPI1_CS_H;
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.device_mode = SPI_MASTER;
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;// SPI 接口逻辑在时钟极性 (CPOL) = 0 和时钟相位 (CPHA) = 0 的情况下运行
spi_init_struct.nss = SPI_NSS_SOFT; //注意 SPI_NSS_HARD是指外部的CS 也就是说对从机有效 主机应该使用SPI_NSS_SOFT
spi_init_struct.prescale = SPI_PSC_32;
spi_init_struct.endian = SPI_ENDIAN_MSB;//大端
spi_init(SPI1,&spi_init_struct);
/* set crc polynomial */
spi_crc_polynomial_set(SPI1,7);
spi_crc_on(SPI1);
/* enable SPI1 */
spi_enable(SPI1);
}
我使用了,可是实际上示波器没有监测到下发的正常校验结果
spi_crc_polynomial_set(SPI1,7);
spi_crc_on(SPI1);
发送数据填充
{
Afex->Spi_Txbuf[0] = Afex->Aevaddr;
Afex->Spi_Txbuf[1] = 0xFF;
//Afex->Spi_Txbuf[2] = CRC8(Afex->Spi_Txbuf, 2);
AFE1_CS_L;
SPI1_TransmitReceiveDma(Afex->Spi_Txbuf, Afex->Afe_Rxbuf, 2);
AFE1_CS_H;
}
//DMA数据填充和发送使能等这里用了个信号量阻塞
uint8_t SPI1_TransmitReceiveDma(const uint8_t * data_tx, uint8_t * data_rx,const uint8_t length)
{
uint8_t result = 0;
taskENTER_CRITICAL();
dma_memory_address_config(DMA0,DMA_CH4,(uint32_t)data_tx);
dma_transfer_number_config(DMA0,DMA_CH4,length);
dma_memory_address_config(DMA0,DMA_CH3,(uint32_t)data_rx);
dma_transfer_number_config(DMA0,DMA_CH3,length+1);
spi_enable(SPI1);
dma_channel_enable(DMA0, DMA_CH4);
dma_channel_enable(DMA0, DMA_CH3); /* 使能 DMA 数据流 */
spi_dma_enable(SPI1, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI1, SPI_DMA_RECEIVE); /* 使能 SPI DMA 请求 */
taskEXIT_CRITICAL();
result = (xSemaphoreTake(spi1_txComplete, 50) == pdTRUE) &&
(xSemaphoreTake(spi1_rxComplete, 50) == pdTRUE); /* 等待传输完成 */
taskENTER_CRITICAL();
spi_disable(SPI1);
taskEXIT_CRITICAL();
return result;
}
//中断监测函数监测到发送或接收完毕后释放信号量接触发送现场阻塞
void spi1TxDmaIsr(void)
{
if(dma_interrupt_flag_get(DMA0,DMA_CH4,DMA_INT_FLAG_FTF)){
dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INT_FLAG_G); /* 清除中断标志位 */
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
// dma_interrupt_disable(DMA0, DMA_CH4, DMA_INT_FTF);
dma_flag_clear(DMA0, DMA_CH4, DMA_FLAG_FTF); /*停止并清除 DMA 数据流 */
spi_dma_disable(SPI1, SPI_DMA_TRANSMIT); /* 关闭 SPI DMA 请求 */
dma_channel_disable(DMA0, DMA_CH4); /* 关闭数据流 */
xSemaphoreGiveFromISR(spi1_txComplete, &xHigherPriorityTaskWoken); /* 释放信号量 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
void spi1RxDmaIsr(void)
{
if(dma_interrupt_flag_get(DMA0,DMA_CH3,DMA_INT_FLAG_FTF)){
dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INT_FLAG_G); /* 清除中断标志位 */
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
// dma_interrupt_disable(DMA0, DMA_CH3, DMA_INT_FTF);
dma_flag_clear(DMA0, DMA_CH3, DMA_FLAG_FTF); /* 停止并清除 DMA 数据流 */
spi_dma_disable(SPI1, SPI_DMA_RECEIVE); /* 关闭 SPI DMA 请求 */
dma_channel_disable(DMA0, DMA_CH3); /* 关闭数据流 */
xSemaphoreGiveFromISR(spi1_rxComplete, &xHigherPriorityTaskWoken); /* 释放信号量 */
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
以上是SPI 驱动收发相关的配置,实际上并没有发出正确的校验值。
认为硬件crc会自动填充一位8bit数据到末尾的缓存区,官方文档对此说明很少。
赞0
评论
2024-10-16
赞0
评论
2024-10-16
赞0
评论
2024-10-16
赞0
评论
2024-10-16
赞0
评论
2024-10-15
赞0
评论
2024-10-15
赞0
评论
2024-10-15
赞0
评论
2024-10-15
赞0
评论
2024-10-15
您需要登录后才可以回复 登录 | 注册