一场疫情让公司的生意越来越好,忙得不可开交,产品特卖。ST单片机交货期不稳定,供应缓慢,价格翻了一番。无奈之下,我不得不从国产单片机开始。所以有我ST-GD代码移植。
目录
- 一、SPI初始化
- 二、DMA配置
- 三、读取数据
一、SPI初始化
/************************************************ 函数名称 : rcu_config 功 能 : RCU时钟配置 参 数 : 无 返 回 值 : 无 作 者 : Mico *************************************************/ void rcu_config(void) {
rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_DMA); rcu_periph_clock_enable(RCU_SPI0); } /************************************************ 函数名称 : gpio_config 功 能 : SPI映射GPIO初始化 参 数 : 无 返 回 值 : 无 作 者 : Mico *************************************************/ void gpio_config(void) {
rcu_config(); /* SPI0 GPIO config: SCK/PA5, MISO/PA6, MOSI/PA7 */ gpio_af_set(GPIOB, GPIO_AF_0, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); gpio_output_options_set(GPIOB,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); gpio_bit_reset(GPIOB,GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);
gpio_bit_set(GPIOA,GPIO_PIN_15);//拉低片选
}
/************************************************ 函数名称 : spi_config 功 能 : SPI 初始化 参 数 : 无 返 回 值 : 无 作 者 : Mico *************************************************/
void spi_config(void)
{
spi_parameter_struct spi_init_struct;
/* deinitilize SPI and the parameters */
spi_i2s_deinit(SPI0);
spi_struct_para_init(&spi_init_struct);
/* SPI0 parameter config */
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_2EDGE;
spi_init_struct.nss = SPI_NSS_SOFT;
spi_init_struct.prescale = SPI_PSC_8;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(SPI0, &spi_init_struct);
}
GD32的SPI配置和ST的方式差不多,区别就在于库函数的封装方式不同。
二、DMA配置
/************************************************ 函数名称 : dma_config 功 能 : SPI DMA初始化 参 数 : 无 返 回 值 : 无 作 者 : Mico *************************************************/
void dma_config(void)
{
dma_parameter_struct dma_init_struct;
dma_struct_para_init(&dma_init_struct);
/* SPI0 transmit dma config */
dma_deinit(DMA_CH2);
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);//外设基地址
dma_init_struct.memory_addr = (uint32_t)SPI_TX_BUF ;//内存基地址
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; //数据传输方向:内存到外设
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;//外设数据宽度8位
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; //内存数据宽度8位
dma_init_struct.priority = DMA_PRIORITY_HIGH; //DMA通道传输软件优先级
dma_init_struct.number = ARRAYSIZE; //DMA通道数据传输数量
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//外设地址生成算法模式使能
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//存储器地址生成算法模式失能
dma_init(DMA_CH2, &dma_init_struct); //初始化DMA通道2
// dma_circulation_enable(DMA_CH2); //DMA循环模式使能
/* SPI0 receive dma config */
dma_deinit(DMA_CH1);
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);
dma_init_struct.memory_addr = (uint32_t)spi0_receive_array;
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
dma_init(DMA_CH1, &dma_init_struct);
// dma_circulation_enable(DMA_CH1);
}
三、读取数据
/************************************************ 函数名称 : SPI_DMA_WriteReadByte 功 能 : SPI DMA读取角度 参 数 : 无 返 回 值 : 无 作 者 : Mico *************************************************/
void SPI_DMA_WriteReadByte(void)
{
GPIO_BC (GPIOA) = (uint32_t)GPIO_PIN_15;
SPI_CTL1(SPI0) |= (uint32_t)SPI_CTL1_DMATEN; /*SPI DMA发送使能*/
SPI_CTL1(SPI0) |= (uint32_t)SPI_CTL1_DMAREN;/*SPI DMA接收使能*/
DMA_CHCTL(DMA_CH2) &= ~DMA_CHXCTL_CHEN; /*失能DMA通道2*/
DMA_CHCNT(DMA_CH2) = ARRAYSIZE ; /*传输长度*/
DMA_CHCTL(DMA_CH2) |= DMA_CHXCTL_CHEN; /*使能DMA通道2*/
dma_channel_disable(DMA_CH1); /*失能DMA通道2*/
// DMA_CHCTL(DMA_CH1) &= ~DMA_CHXCTL_CHEN;
DMA_CHCNT(DMA_CH1) = ARRAYSIZE ; /*传输长度*/
// DMA_CHCTL(DMA_CH1) |= DMA_CHXCTL_CHEN;
dma_channel_enable(DMA_CH1); /*使能DMA通道2*/
while(RESET == dma_flag_get(DMA_CH2,DMA_FLAG_FTF));
while(RESET == dma_flag_get(DMA_CH1,DMA_FLAG_FTF));
GPIO_BOP(GPIOA) = (uint32_t)GPIO_PIN_15;
}
依旧是ST的那个味道,一开始我用GD给的例程写的SPI通信,发现数据只能读取一次。最后还是用ST的那个思想,先失能DMA通道,再重新定义数据长度,再使能DMA通道。因为我SPI的发送和接收都是使用DMA方式,所以使用了两个通道。通道2的发送和通道1的接收。PA15是SPI的使能引脚。