串口:
一. USART_ITConfig(USART1, USART_IT_TXE, ENABLE):
只要發(fā)送寄存器為空,就會一直有中斷,因此,要是不發(fā)送數(shù)據(jù)時,把發(fā)送中斷關閉,只在開始發(fā)送時,才打開。
二.
以下是字符發(fā)送的配置過程,注意第6點,在設置USART_CR1中的TE位時,會發(fā)送一個空閑幀作為第一次數(shù)據(jù)發(fā)送,所以即便你執(zhí)行了USART_ClearFlag(USART1, USART_FLAG_TC); (這個函數(shù)肯定在空閑幀數(shù)據(jù)發(fā)送完成前執(zhí)行),所以當空閑幀發(fā)送完后,就進入發(fā)送完成中斷。
配置步驟:
1.通過在USART_CR1寄存器上置位UE位來激活USART
2.編程USART_CR1的M位來定義字長。
3.在USART_CR2中編程停止位的位數(shù)。
4.如果采用多緩沖器通信,配置USART_CR3中的DMA使能位(DMAT)。按多緩沖器通信中
的描述配置DMA寄存器。
5.利用USART_BRR寄存器選擇要求的波特率。
6.設置USART_CR1中的TE位,發(fā)送一個空閑幀作為第一次數(shù)據(jù)發(fā)送。
7.把要發(fā)送的數(shù)據(jù)寫進USART_DR寄存器(此動作清除TXE位)。在只有一個緩沖器的情況
下,對每個待發(fā)送的數(shù)據(jù)重復步驟7。
8.在USART_DR寄存器中寫入最后一個數(shù)據(jù)字后,要等待TC=1,它表示最后一個數(shù)據(jù)幀的
傳輸結束。當需要關閉USART或需要進入停機模式之前,需要確認傳輸結束,避免破壞
最后一次傳輸。
解決的辦法:
方法一
在執(zhí)行USART_ITConfig(USART1,USART_IT_TC, ENABLE); 之前,
先延時一段時間,基本上比一個字符發(fā)送的時間長一點就可以了,然后再執(zhí)行
USART_ClearFlag(USART1, USART_FLAG_TC);
方法二:
在執(zhí)行USART_ITConfig(USART1,USART_IT_TC, ENABLE); 之前,
USART_ClearFlag(USART1, USART_FLAG_TC);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)
{
; //等待空閑幀發(fā)送完成后再清零發(fā)送標志
}
USART_ClearFlag(USART1,USART_FLAG_TC);
三.
TXE:發(fā)送緩沖器空閑標志
RXNE:接收緩沖區(qū)非空
IAP:
一.
問:
這幾天在折騰STM32的IAP,參考了兩個例程,一個AN2557,然后一個就是標準外設庫內的flash例程
總結IAP:
1.Flash解鎖FLASH_Unlock();
2.清除Flash所有的未完成的標志位FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
3.根據(jù)文件大小擦除Flash
for(EraseCounter=0;(EraseCounter
FLASHStatus=FLASH_ErasePage(StartAddr+(FLASH_PAGE_SIZE*EraseCounter));
}
4.編程Flash
while((Address
FLASHStatus=FLASH_ProgramWord(Address,Data);
Address=Address+4;
}
5.檢驗編入數(shù)據(jù)的正確性
while((Address
if((*(__IOuint32_t*)Address)!=Data)
{
MemoryProgramStatus=FAILED;
}
Address+=4;
}
在以上幾步中,如果上面沒有問題的話,提出下面幾個疑問
1.假如我的應用程序的地址應該從0x8003000開始,那么我把后面的頁全部擦除是否可以?雖然我的程序可能只占到0x8003000-0x8005000那么這之后的頁是否也可以一并擦除?
2.在編程的時候有個很小的問題,因我的數(shù)據(jù)都是以字節(jié)(byte)的形式儲存的,在寫的時候因為只能以半字(16位)或一個字(32位)的方式編程,那么如果我的bin
文件的最后一個字節(jié)并不夠兩個字節(jié),怎么辦?舉例:我的bin文件的大小是501個字節(jié)(8位),我的寫入方法是這樣的:
data[501]={X,X,X...}//應用程序bin文件內容
temp=data[0];
temp=temp<<8;
temp|=data[1];
temp=temp<<8;
temp|=data[2];
teme=temp<<8;
teme|=data[3];//待寫入得數(shù)據(jù)
FLASHStatus=FLASH_ProgramWord(Address,temp);//寫入flash
如果像這樣的話,那么不能被4整除的那一個字節(jié)怎么辦?
3.IAP程序中有一處一直很迷惑,不能理解
/*Testifusercodeisprogrammedstartingfromaddress"ApplicationAddress"*/
if(((*(__IOuint32_t*)ApplicationAddress)&0x2FFE0000)==0x20000000)
{/*Jumptouserapplication*/
JumpAddress=*(__IOuint32_t*)(ApplicationAddress+4);
Jump_To_Application=(pFunction)JumpAddress;
/*Initializeuserapplication'sStackPointer*/
__set_MSP(*(__IOuint32_t*)ApplicationAddress);
Jump_To_Application();
}
程序的整體是要跳出IAP引導區(qū)跳到應用程序區(qū).那么這句判斷的依據(jù)是什么?if(((*(__IOuint32_t*)ApplicationAddress)&0x2FFE0000)==0x20000000)
倘若我今天的程序是重0x8003000處開始,那么明天我升級一個程序,他的開始是0x80080000呢?這里需要改嗎?
0x2FFE00000x20000000這兩個數(shù)我在AN2557的例子代碼里反復尋找,并沒有哪里出現(xiàn),那么又是怎么跟用戶的應用程序關聯(lián)的呢?
還有如果將上面的例子直接這樣更改,是否可以達到跳轉到應用程序區(qū)的目的呢?
/*Jumptouserapplication*/
JumpAddress=*(__IOuint32_t*)(ApplicationAddress+4);//這里為何要+4?+了4不就跳過出應用程序的入口了嗎?
Jump_To_Application=(pFunction)JumpAddress;
/*Initializeuserapplication'sStackPointer*/
__set_MSP(*(__IOuint32_t*)ApplicationAddress);
Jump_To_Application();
4.關于Flash的寫保護問題,在3.0標準外設庫中Flash還有另外一個例子,就是關于保護的
無疑flash的保護是對程序的一個安全保障,但目前我買的新片子(未進行過任何保護方面的操作)中,是否不需要考慮這些問題,直接擦除,然后編程即可?
5.有什么理由要“今天的程序是重0x8003000處開始,明天又升級一個程序,他的開始是呢”?第1沒有必要,第2是自尋煩惱。開始地址是你自己定的,為什么要自己為難自己?
這個問題怪我沒說清楚,其實我是想說,我現(xiàn)在的引導區(qū)這樣定義的#ApplicationAddress0x80030000我只能啟動起始地址在0x08003000處的應用程序,那么這段代碼是可以成功啟動的(我驗證過):
/*Testifusercodeisprogrammedstartingfromaddress"ApplicationAddress"*/
if(((*(__IOuint32_t*)ApplicationAddress)&0x2FFE0000)==0x20000000)
{/*Jumptouserapplication*/
JumpAddress=*(__IOuint32_t*)(ApplicationAddress+4);
Jump_To_Application=(pFunction)JumpAddress;
/*Initializeuserapplication'sStackPointer*/
__set_MSP(*(__IOuint32_t*)ApplicationAddress);
Jump_To_Application();
}
那如果我現(xiàn)在想引導啟動地址在0x80080000的應用程序,是否只要更改#ApplicationAddress0x80080000這句就好?上面那串代碼就不需要更改了吧?
我還是想理解了上面的那串代碼到底是為什么?希望香版能仔細幫我解釋下,(當我白癡好了,呵呵)!
答:
1.可以,只要不影響功能就行
2.比較好的解決方法,先讀一頁出來到RAM,擦掉這一頁Flash,在RAM中修改相應的Bytes,再將整頁寫回去?!∫话愕慕鉀Q方法,后面不足一個WORD/DWORD的補0xff或0x00,補齊一個WORD或DWORD
3.ApplicationAddress對應著你的應用程序"stm32f10x_vector.c"這個文件中的__vector_table
*(__IOuint32_t*)ApplicationAddress與__vector_table[0]是一樣的
*(__IOuint32_t*)(ApplicationAddress+4)與__vector_table[1]是一樣的
__vector_table[0]是應用程序棧的頂
__vector_table[1]是應用程序的啟動地址
這里有討論過
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1600156&bbs_page_no=3&bbs_id=3020
(X&0x2FFE0000)==0x20000000意思是說X是不是在0x20000000與0x2001FFFF之間,即棧頂是不是在以0x20000000開始的128K
的范圍內,這里便是STM32的RAM區(qū)域,雖然現(xiàn)在最大的只有64k
如果你的bootloader只能啟動0x08003000的應用程序,那么你寫一個起始地址在0x08008000的程序他將不能啟動
你要寫一個在0x080003000的啟動程序來啟動0x08008000的應用程序,或者把0x08008000前八字節(jié)的內容放到0x08003000中
4.是的,買回來的可以直接寫,出廠時芯片的Flash都沒有設置保護。