CH32V103C8T6 FLASH讀數(shù)據(jù)異常,求助

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

經(jīng)過(guò)這兩天的測(cè)試,F(xiàn)LASH讀數(shù)據(jù)異常問(wèn)題可穩(wěn)定復(fù)現(xiàn),復(fù)現(xiàn)過(guò)程如下:

新建一個(gè)工程,新建關(guān)于FLASH操作的文件,包含兩個(gè)函數(shù):一個(gè)向指定地址寫數(shù)據(jù),一個(gè)讀指定地址數(shù)據(jù)。

在main.c中,先向指定地址寫數(shù)據(jù)01,然后讀該地址數(shù)據(jù),之后再向該地址寫數(shù)據(jù)02,最后讀該地址數(shù)據(jù)并打印輸出。

理論上打印輸出值應(yīng)該為02,但實(shí)際打印輸出值為01。

相關(guān)代碼如下:

FLASH操作文件的兩個(gè)函數(shù):

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位數(shù)據(jù))

uint16_t FLASH_ReadHalfWord(uint32_t address) {

? ? return *(__IO uint16_t*) address;

}


MAIN.C的相關(guān)代碼:

int main(void) {

? ? GPIO_InitTypeDef GPIO_t;

? ? u16 n1, n2;


? ? NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

? ? Delay_Init();

? ? USART_Printf_Init(9600);


? ? //485設(shè)置為輸出模式

? ? 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);

? ? ? ? }

? ? }

}



--------------------------------------------以下是原問(wèn)題描述----------------------------------------------------------

使用CH32V103C8T6,通過(guò)RS485通訊發(fā)送指令修改RS485通訊地址,寫完數(shù)據(jù)之后馬上讀取以驗(yàn)證寫數(shù)據(jù)是否成功,但讀出的數(shù)據(jù)仍是寫之前的舊的485地址。開(kāi)始以為是寫數(shù)據(jù)失敗,但通過(guò)讀地址指令讀出來(lái)的地址又是更改后的地址,在OLED顯示界面調(diào)取485地址,也是寫后的新地址。

但是在處理485通訊的函數(shù)內(nèi),寫完485地址,馬上去讀寫入后的地址,讀出來(lái)的卻始終是原來(lái)的舊地址。


程序部分代碼如下:

if (regValue[0] == 0 || regValue[0] > 247) //按協(xié)議,地址范圍在1-247

? ? ? ? ? ? ? ? return;


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


????????????//測(cè)試用,正式版刪除

? ? ? ? ? ? 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;


????????????//驗(yàn)證寫地址是否成功

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

? ? ? ? ? ? ? ? return;

以上代碼寫數(shù)據(jù)是成功的,后續(xù)用讀485地址指令可以正常讀出更改后的新485地址,在OLED顯示界面調(diào)出485地址也是新的地址。

但在寫完后馬上讀數(shù)據(jù)以驗(yàn)證寫入是否成功的時(shí)候,讀出的數(shù)據(jù)卻始終是舊的數(shù)據(jù)。


熱門產(chǎn)品 : USB3.0 HUB控制器:CH634

早上繼續(xù)就此問(wèn)題進(jìn)行測(cè)試,在另一段寫數(shù)據(jù)的操作中,寫完數(shù)據(jù)后馬上讀取又是正常的??梢哉7祷貙懞蟮臄?shù)據(jù),該段代碼如下:

if (regaddr == MB_REGADDR_DeviceID)?

? ? ? ? {

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

? ? ? ? ? ? ? ? return;


? ? ? ? ? ? reg_cnt = msg_t->rx_buf[5]; //寄存器數(shù)量應(yīng)為2

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

? ? ? ? ? ? ? ? return;


? ? ? ? ? ? if (msg_t->rx_buf[6] != 4)? //字節(jié)數(shù)應(yīng)為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);


上面這段代碼執(zhí)行又是正常的,上位機(jī)發(fā)送寫DeviceID命令后,可以正常返回?cái)?shù)據(jù)。

而另外幾條寫命令,都是寫數(shù)據(jù)實(shí)際是成功的,但在寫完數(shù)據(jù)后驗(yàn)證寫數(shù)據(jù)是否成功時(shí)馬上去讀出的數(shù)據(jù)為寫前的數(shù)據(jù)導(dǎo)致從機(jī)無(wú)法正常返回寫成功的信息。

但如果通過(guò)讀命令卻可以讀出寫后的數(shù)據(jù)。


另外如果在向FLASH寫數(shù)據(jù)的函數(shù)里添加一段OLED顯示字符的代碼后,再發(fā)送寫485地址命令,從機(jī)可以正常返回新的485地址。真是奇怪。


最新的測(cè)試結(jié)果是:

設(shè)地址0x0800F000的地址有數(shù)據(jù)0x01,通過(guò)通訊向該地址寫0x02,寫完后馬上讀取,會(huì)讀出0x01。但如果在寫完數(shù)據(jù)的代碼后面添加如上的OLED顯示字符的代碼后再讀,可以正常讀出0x02。將OLED顯示字符的代碼去掉,改為讀另一個(gè)地址如0x0800E000的數(shù)據(jù),然后再讀0x0800F000的數(shù)據(jù),也可以正常讀出0x02


您好,按照我對(duì)你問(wèn)題的理解,你是在FLASH某個(gè)地址(比如0x0800F000)寫入數(shù)據(jù)之后立馬去讀,讀出數(shù)據(jù)為之前的數(shù)據(jù),并不是剛剛的寫入的數(shù)據(jù)。下圖為我模擬你的操作寫的程序,寫入之后立馬讀是沒(méi)有問(wèn)題的。這邊建議你在往FLASH某個(gè)地址寫入數(shù)據(jù)的時(shí)候,先解鎖,然后擦除,再調(diào)用FLASH_ProgramHalfWord函數(shù)寫入數(shù)據(jù),如下圖,你可以按照下圖試一下。后續(xù)若有問(wèn)題,可通過(guò)郵箱(lzs@wch.cn)繼續(xù)和我溝通,附件為參考例程,可以看一下。

icon_rar.gifCH32V103 FLASH讀寫.zip

image.png


感謝回復(fù)。

我這邊測(cè)試的結(jié)果是只有在某些條件才會(huì)出現(xiàn)這種情況,在另外一些情況下又不會(huì),具體原因未知。向FLASH寫數(shù)據(jù),是嚴(yán)格參考的官方例程,而且寫數(shù)據(jù)是成功的。只是在寫完數(shù)據(jù)馬上去讀取才會(huì)有時(shí)候出現(xiàn)異常,但在另外一些場(chǎng)景,寫完數(shù)據(jù)馬上去讀取,又是完全正常的。

具體情況已發(fā)郵件。


只有登錄才能回復(fù),可以選擇微信賬號(hào)登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频