-
使用 DMA写flash后,读取数据出现错位现象
使用 DMA写flash后,读取数据出现错位现象,读到的buffer 的第一节总为0,从第二字节开始才是正常数据。只能在24bit地址发送完后,再发一个DUMMY_BYTE(无效字节),才能bufferr接收数据。 一但调“dma_channel_enable(DMA1, DMA_CH3)这个使能”后就出现上述现象。每次读取数据时都要先发一个DUMMY_BYTE才能正确接收。若上电不调“dma_channel_enable(DMA1, DMA_CH3)“接收都是正常的。使用的MCU是GD32F470VIT6,SPI FLAH是GD25Q40C. 请各位大佬帮忙分析下。 以下为SPI代码 DMA配置 void dma_init(uint8_t *data_buffer, uint32_t data_length) { dma_single_data_parameter_struct dma_init_struct; rcu_periph_clock_enable(RCU_DMA1); //DMA发送 dma_deinit(DMA1, DMA_CH3); // DMA初始化参数设置 dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; dma_init_struct.memory0_addr = (uint32_t)data_buffer; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = data_length; dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE; dma_init_struct.priority = DMA_PRIORITY_MEDIUM; dma_single_data_mode_init(DMA1, DMA_CH3, &dma_init_struct); dma_channel_subperipheral_select(DMA1, DMA_CH3, DMA_SUBPERI3); // 使能DMA中断通道 nvic_irq_enable(DMA1_Channel3_IRQn, 0, 0); // 配置DMA中断使能位 //dma_circulation_disable(DMA1, DMA_CH3); dma_interrupt_enable(DMA1, DMA_CH3, DMA_CHXCTL_FTFIE); } DMA发送 int8_t spi_dma_data_send(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write) { /* enable the write access to the flash */ spi_flash_write_enable(); /* select the flash: chip select low */ SPI_FLASH_CS_LOW(); /* send "write to memory" instruction */ spi_flash_send_byte(WRITE); /* send read_addr high nibble address byte to read from */ spi_flash_send_byte((write_addr & 0xFF0000) >> 16); /* send read_addr medium nibble address byte to read from */ spi_flash_send_byte((write_addr& 0xFF00) >> 8); /* send read_addr low nibble address byte to read from */ spi_flash_send_byte(write_addr & 0xFF); dma_channel_disable(DMA1, DMA_CH3); spi_dma_disable(SPI0,SPI_DMA_TRANSMIT); dma_memory_address_config(DMA1, DMA_CH3, DMA_MEMORY_0, (uint32_t)(pbuffer)); dma_transfer_number_config(DMA1, DMA_CH3, num_byte_to_write); spi_dma_enable(SPI0,SPI_DMA_TRANSMIT); dma_channel_enable(DMA1, DMA_CH3); return 0; } DMA接收 int8_t spi_dma_data_recv(uint8_t* pbuffer, uint32_t read_addr, uint16_t num_byte_to_write) { uint8_t dumyy_byte = 0xA5; //spi_flash_wait_for_write_end(); /* select the flash: chip slect low */ SPI_FLASH_CS_LOW(); /* send "read from memory " instruction */ spi_flash_send_byte(READ); /* send read_addr high nibble address byte to read from */ spi_flash_send_byte((read_addr & 0xFF0000) >> 16); /* send read_addr medium nibble address byte to read from */ spi_flash_send_byte((read_addr& 0xFF00) >> 8); /* send read_addr low nibble address byte to read from */ spi_flash_send_byte(read_addr & 0xFF); spi_flash_send_byte(0xA5); //为应对错位,多加的一个DUMMY_BYTE dma_channel_disable(DMA1, DMA_CH3); dma_channel_disable(DMA1, DMA_CH2); spi_dma_disable(SPI0,SPI_DMA_TRANSMIT); spi_dma_disable(SPI0,SPI_DMA_RECEIVE); dma_memory_address_config(DMA1, DMA_CH3, DMA_MEMORY_0, (uint32_t)(&dumyy_byte)); //设置发送无效字节 dma_periph_width_config(DMA1, DMA_CH3, DMA_MEMORY_INCREASE_DISABLE);//取消地址自动增长 dma_transfer_number_config(DMA1, DMA_CH3, num_byte_to_write);//设置产生时钟脉冲个数 dma_memory_address_config(DMA1, DMA_CH2, DMA_MEMORY_0, (uint32_t)pbuffer);//设置接收数据位 dma_transfer_number_config(DMA1, DMA_CH2, num_byte_to_write);//设置产生时钟脉冲个数 /* enable DMA channel */ spi_dma_enable(SPI0,SPI_DMA_TRANSMIT); //SPI使能DMA发送功能 spi_dma_enable(SPI0,SPI_DMA_RECEIVE); /* enable DMA channel */ dma_channel_enable(DMA1, DMA_CH2); //使能DMA接收 dma_channel_enable(DMA1, DMA_CH3); //使能DMA发送 /* while there is data to be written on the flash */ } spi初始化 void spi_flash_init(void) { spi_parameter_struct spi_init_struct; rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_SPI0); /* SPI0_CLK(PB3), SPI0_MISO(PB4), SPI0_MOSI(PB5) GPIO pin configuration */ gpio_af_set(GPIOB, GPIO_AF_5, 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_25MHZ, GPIO_PIN_3|GPIO_PIN_4| GPIO_PIN_5); /* SPI0_CS(PE2) GPIO pin configuration */ rcu_periph_clock_enable(RCU_GPIOE); gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2); gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); /* chip select invalid */ SPI_FLASH_CS_HIGH(); /* 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_1EDGE; spi_init_struct.nss = SPI_NSS_SOFT; spi_init_struct.prescale = SPI_PSC_32; spi_init_struct.endian = SPI_ENDIAN_MSB; spi_init(SPI0, &spi_init_struct); /* enable SPI0 */ spi_enable(SPI0); }
3633浏览量 15回复量 关注量 -
如何读取TIMERx的计数值 sos
在STM32 F系列芯片中测试GPIO输出速度还行轻松达到10MHz以上,我的问题是:如果用外部信号触发时钟time用内部系统时钟计数测试的数值在time里,如何读出? 用CubeMX常见的工程,遍历与时钟相关的函数没有找到读取值得方法。 知情者请告知,先谢谢了。
2177浏览量 0回复量 关注量 -
i2c读从设备问题,不知道为何只能读到1个字节
读取代码如下:uint8_t read_len(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf) { while(i2c_flag_get(I2CX, I2C_FLAG_I2CBSY)); i2c_start_on_bus(I2CX); while(!i2c_flag_get(I2CX, I2C_FLAG_SBSEND)); i2c_master_addressing(I2CX, addr << 1, I2C_TRANSMITTER); while(!i2c_flag_get(I2CX, I2C_FLAG_ADDSEND)); i2c_flag_clear(I2CX, I2C_FLAG_ADDSEND); while(!i2c_flag_get(I2CX, I2C_FLAG_TBE)); i2c_data_transmit(I2CX, reg); while(!i2c_flag_get(I2CX, I2C_FLAG_BTC)); i2c_start_on_bus(I2CX); while(!i2c_flag_get(I2CX, I2C_FLAG_SBSEND)); /* send slave address to I2C bus */ i2c_master_addressing(I2CX, addr << 1, I2C_RECEIVER); while(!i2c_flag_get(I2CX, I2C_FLAG_ADDSEND)); i2c_flag_clear(I2CX, I2C_FLAG_ADDSEND); i2c_ackpos_config(I2CX, I2C_ACKPOS_NEXT); while(len){ if (1 == len){ i2c_ackpos_config(I2CX, I2C_ACKPOS_CURRENT); i2c_ack_config(I2CX, I2C_ACK_DISABLE); } if (i2c_flag_get(I2CX, I2C_FLAG_RBNE)){ // 读到1个字节之后,if语句就再也不能为真了,导致读不到更多内容。 *buf = i2c_data_receive(I2CX); i2c_ack_config(I2CX, I2C_ACK_ENABLE); buf++; len--; } } i2c_stop_on_bus(I2CX); while(I2C_CTL0(I2CX) & 0x0200); return 0; } 使用的开发板为GD32F330C8T6。用GD32F3x0_Firmware_Library_V2.2.1里面的I2C_EEPROM例子程序也是同样的问题,只能读取一个字节,好让人费解啊。请各位不吝赐教,万分感谢。
1592浏览量 1回复量 关注量