CH32V103C8T6 FLASH读数据异常,求助

------------230303更新--------------------

经过这两天的测试,FLASH读数据异常问题可稳定复现,复现过程如下:

新建一个工程,新建关于FLASH操作的文件,包含两个函数:一个向指定地址写数据,一个读指定地址数据。

在main.c中,先向指定地址写数据01,然后读该地址数据,之后再向该地址写数据02,最后读该地址数据并打印输出。

理论上打印输出值应该为02,但实际打印输出值为01。

相关代码如下:

FLASH操作文件的两个函数:

void Flash_save(u16 dat) {

? ? FLASH_Unlock_Fast();

? ? FLASH_ErasePage_Fast(0x0800E080);

? ? FLASH_BufReset();

? ? FLASH_BufLoad(0x0800E080, dat, 0, 0, 0);

? ? FLASH_ProgramPage_Fast(0x0800E080);

? ? FLASH_Lock_Fast();

}


//读取指定地址的半字(16位数据)

uint16_t FLASH_ReadHalfWord(uint32_t address) {

? ? return *(__IO uint16_t*) address;

}


MAIN.C的相关代码:

int main(void) {

? ? GPIO_InitTypeDef GPIO_t;

? ? u16 n1, n2;


? ? NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

? ? Delay_Init();

? ? USART_Printf_Init(9600);


? ? //485设置为输出模式

? ? GPIO_t.GPIO_Mode = GPIO_Mode_Out_PP;

? ? GPIO_t.GPIO_Speed = GPIO_Speed_50MHz;

? ? GPIO_t.GPIO_Pin = GPIO_Pin_8;

? ? GPIO_Init(GPIOA, &GPIO_t);


? ? GPIO_SetBits(GPIOA, GPIO_Pin_8);


? ? printf("SystemClk:%d\r\n", SystemCoreClock);


? ? printf("This is printf example\r\n");

? ? n2 = 0;

? ? Flash_save(0x01);


? ? while(1)

? ? {

? ? ? ? if (n2 < 1000)

? ? ? ? {

? ? ? ? ? ? ++n2;

? ? ? ? ? ? printf("test flash save read\r\n");

? ? ? ? ? ? Delay_Ms(3000);

? ? ? ? ? ? //n1 = *(u16 *)(0x0800E080);

? ? ? ? ? ? n1 = FLASH_ReadHalfWord(0x0800e080);

? ? ? ? ? ? Flash_save(0x20);

? ? ? ? ? ? //n1 = *(u16 *)(0x0800E080);

? ? ? ? ? ? n1 = FLASH_ReadHalfWord(0x0800e080);

? ? ? ? ? ? printf("n1=:%d\r\n",n1);

? ? ? ? }

? ? }

}



--------------------------------------------以下是原问题描述----------------------------------------------------------

使用CH32V103C8T6,通过RS485通讯发送指令修改RS485通讯地址,写完数据之后马上读取以验证写数据是否成功,但读出的数据仍是写之前的旧的485地址。开始以为是写数据失败,但通过读地址指令读出来的地址又是更改后的地址,在OLED显示界面调取485地址,也是写后的新地址。

但是在处理485通讯的函数内,写完485地址,马上去读写入后的地址,读出来的却始终是原来的旧地址。


程序部分代码如下:

if (regValue[0] == 0 || regValue[0] > 247) //按协议,地址范围在1-247

? ? ? ? ? ? ? ? return;


? ? ? ? ? ? Flash_Save_RS485ID(regValue[0]);


????????????//测试用,正式版删除

? ? ? ? ? ? tx_buf[2] = msg_t->rx_buf[2];

? ? ? ? ? ? tx_buf[3] = msg_t->rx_buf[3];

? ? ? ? ? ? regValue[1] = FLASH_ReadHalfWord(SIMD_RS485_BASE_ADDR);??

? ? ? ? ? ? tx_buf[4] = regValue[1]>>8;

? ? ? ? ? ? tx_buf[5] = regValue[1];

? ? ? ? ? ? RS485_SendData(tx_buf, 6);

? ? ? ? ? ? return;


????????????//验证写地址是否成功

? ? ? ? ? ? if (regValue[0] != *(u16 *) (SIMD_RS485_BASE_ADDR))

? ? ? ? ? ? ? ? return;

以上代码写数据是成功的,后续用读485地址指令可以正常读出更改后的新485地址,在OLED显示界面调出485地址也是新的地址。

但在写完后马上读数据以验证写入是否成功的时候,读出的数据却始终是旧的数据。

早上继续就此问题进行测试,在另一段写数据的操作中,写完数据后马上读取又是正常的。可以正常返回写后的数据,该段代码如下:

if (regaddr == MB_REGADDR_DeviceID)?

? ? ? ? {

? ? ? ? ? ? if (msg_t->rx_buf[4] != 0x00)

? ? ? ? ? ? ? ? return;


? ? ? ? ? ? reg_cnt = msg_t->rx_buf[5]; //寄存器数量应为2

? ? ? ? ? ? if (reg_cnt != 0x02)

? ? ? ? ? ? ? ? return;


? ? ? ? ? ? if (msg_t->rx_buf[6] != 4)? //字节数应为4

? ? ? ? ? ? ? ? return;


? ? ? ? ? ? regValue[0] = msg_t->rx_buf[7] << 8 | msg_t->rx_buf[8];

? ? ? ? ? ? regValue[1] = msg_t->rx_buf[9] << 8 | msg_t->rx_buf[10];

? ? ? ? ? ? Flash_Save_DeviceID((u32) (regValue[1] << 16 | regValue[0]));

? ? ? ? ? ? if (regValue[0] != *(u16 *) (SIMD_DEVICE_BASE_ADDR + ADDR_DeviceID)

? ? ? ? ? ? ? ? ? ? || regValue[1]

? ? ? ? ? ? ? ? ? ? ? ? ? ? != *(u16 *) (SIMD_DEVICE_BASE_ADDR + ADDR_DeviceID

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + 0x02))

? ? ? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? tx_buf[2] = msg_t->rx_buf[2];

? ? ? ? tx_buf[3] = msg_t->rx_buf[3];

? ? ? ? tx_buf[4] = msg_t->rx_buf[4];

? ? ? ? tx_buf[5] = msg_t->rx_buf[5];

? ? ? ? crc16_2 = crc16_table(tx_buf, 6);

? ? ? ? tx_buf[6] = crc16_2 >> 8;

? ? ? ? tx_buf[7] = crc16_2;

? ? ? ? RS485_SendData(tx_buf, 8);


上面这段代码执行又是正常的,上位机发送写DeviceID命令后,可以正常返回数据。

而另外几条写命令,都是写数据实际是成功的,但在写完数据后验证写数据是否成功时马上去读出的数据为写前的数据导致从机无法正常返回写成功的信息。

但如果通过读命令却可以读出写后的数据。


另外如果在向FLASH写数据的函数里添加一段OLED显示字符的代码后,再发送写485地址命令,从机可以正常返回新的485地址。真是奇怪。


最新的测试结果是:

设地址0x0800F000的地址有数据0x01,通过通讯向该地址写0x02,写完后马上读取,会读出0x01。但如果在写完数据的代码后面添加如上的OLED显示字符的代码后再读,可以正常读出0x02。将OLED显示字符的代码去掉,改为读另一个地址如0x0800E000的数据,然后再读0x0800F000的数据,也可以正常读出0x02


您好,按照我对你问题的理解,你是在FLASH某个地址(比如0x0800F000)写入数据之后立马去读,读出数据为之前的数据,并不是刚刚的写入的数据。下图为我模拟你的操作写的程序,写入之后立马读是没有问题的。这边建议你在往FLASH某个地址写入数据的时候,先解锁,然后擦除,再调用FLASH_ProgramHalfWord函数写入数据,如下图,你可以按照下图试一下。后续若有问题,可通过邮箱(lzs@wch.cn)继续和我沟通,附件为参考例程,可以看一下。

icon_rar.gifCH32V103 FLASH读写.zip

image.png


感谢回复。

我这边测试的结果是只有在某些条件才会出现这种情况,在另外一些情况下又不会,具体原因未知。向FLASH写数据,是严格参考的官方例程,而且写数据是成功的。只是在写完数据马上去读取才会有时候出现异常,但在另外一些场景,写完数据马上去读取,又是完全正常的。

具体情况已发邮件。


只有登录才能回复,可以选择微信账号登录