版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、串口設(shè)備驅(qū)動接口STM32的2.0固件庫的工程文檔ourdev_611401K0IJZU.rar(文件大小:227K) (原文件名:串口發(fā)送模板(第二版).rar)STM32的3.0固件庫的工程文檔ourdev_611402L6BK0Z.rar(文件大小:801K) (原文件名:串口發(fā)送模板(第三版).rar)在設(shè)計(jì)串口驅(qū)動的過程中,要遵循的兩條準(zhǔn)則是:1:盡量的減少程序運(yùn)行的時(shí)間。2:盡量的減少程序所占用的內(nèi)存。譬如,下面的一段程序:程序段1-1/*指針是指向ptr,需要發(fā)送count個(gè)數(shù)據(jù)*/void USART1WriteDataToBuffer(*ptr,u8 count) /*判斷數(shù)
2、據(jù)是否發(fā)送完畢*/ while(count-) /*發(fā)送數(shù)據(jù)*/ USART1SendByte(*ptr+); /*等待這個(gè)數(shù)據(jù)發(fā)送完畢,然后進(jìn)入下一個(gè)數(shù)據(jù)的發(fā)送過程*/ while(USART_GetFlagStatus(USART1,USART_FLAG_TC); /*數(shù)據(jù)發(fā)送完畢,返回*/很明顯,這段程序在實(shí)際應(yīng)用中將會產(chǎn)生災(zāi)難性的后果,首先,當(dāng)發(fā)送數(shù)據(jù)送到發(fā)送寄存器啟動發(fā)送以后,CPU就一直在等待這個(gè)數(shù)據(jù)發(fā)送完成,然后進(jìn)入下一個(gè)數(shù)據(jù)的發(fā)送,這樣,直到所有要發(fā)送的數(shù)據(jù)完成,CPU才能做其他的事情。相對于CPU內(nèi)核運(yùn)行的速度而言,串口外設(shè)的運(yùn)行速度是非??斓?,讓一個(gè)速度非??斓脑O(shè)備去等待相
3、對很慢的設(shè)備,程序的效率是非常低下的。所以必須采用中斷的方式發(fā)送數(shù)據(jù)。程序段1-2/*將數(shù)據(jù)寫入發(fā)送緩沖區(qū)*/void USART1WriteDataToBuffer(*ptr,u8 count) while(count!='0') USART1SendTCBIndex+=*ptr+; Count=count; /.判斷溢出等其他代碼省略./.發(fā)送中斷的ISR./void USART1SendUpdate(void) /.判斷發(fā)送緩沖區(qū)中的數(shù)據(jù)是否發(fā)送完畢./ /將發(fā)送緩沖區(qū)的數(shù)據(jù)發(fā)送出去/ USART1SendByte(*ptr+); /.發(fā)送指針加一,待發(fā)送的字節(jié)數(shù)減一等代
4、碼./ 這樣,當(dāng)調(diào)用USART1WriteDataToBuffer函數(shù)將待發(fā)送的數(shù)據(jù)寫入發(fā)送緩沖區(qū)以后,CPU就可以執(zhí)行其他的任務(wù),待一個(gè)數(shù)據(jù)發(fā)送完成以后,中斷ISR就會觸發(fā),在中斷服務(wù)程序里面將下一個(gè)數(shù)據(jù)寫入發(fā)送寄存器,啟動下一次發(fā)送,知道完全發(fā)送完畢為止。 很明顯,上述的程序的設(shè)計(jì)比較好,不用占用過多的CPU時(shí)間。 在實(shí)際的工程應(yīng)用中,經(jīng)常會出現(xiàn)類似這種情況:串口顯示屏需要顯示1000個(gè)點(diǎn),通過串口發(fā)送這1000個(gè)點(diǎn)的顏色的RGB亮度值。將這1000個(gè)數(shù)據(jù)寫入發(fā)送緩沖區(qū)以后,啟動發(fā)送。在115200的波特率,一位起始位,一位停止位,無校驗(yàn)位的情況下,至少需要(10*1000*2)/1152
5、00=0.1736秒,在這期間以內(nèi),時(shí)鐘更新了,需要再發(fā)送給串口一串時(shí)間更新的數(shù)據(jù),這個(gè)數(shù)據(jù)大約有100個(gè),這樣這串?dāng)?shù)據(jù)需要寫入到發(fā)送緩沖區(qū)的發(fā)送字節(jié)的后面。同樣道理,在這個(gè)時(shí)候如果有顯示任務(wù)更新的話,將會有其他的數(shù)據(jù)寫入到發(fā)送緩沖區(qū)。串口1 (原文件名:串口1.JPG) 從圖上可以看出,程序段1-2雖然滿足了時(shí)間上的要求,卻沒有滿足空間上的要求,它的數(shù)據(jù)緩沖區(qū)是單向的,這樣,當(dāng)發(fā)送緩沖區(qū)的所有的數(shù)據(jù)全部發(fā)送完畢后,或者當(dāng)發(fā)送緩沖區(qū)撐滿了以后才能將發(fā)送緩沖區(qū)內(nèi)的數(shù)據(jù)清空,以便裝入下次的緩沖數(shù)據(jù)。這樣內(nèi)存較小的嵌入式系統(tǒng)來說是不能容忍的。因此,可以將發(fā)送緩沖區(qū)建立成一個(gè)環(huán)形的緩沖區(qū),在這個(gè)環(huán)形緩
6、沖區(qū)內(nèi),通過頭指針(HostIndex)和尾指針(HostIndex)來定位空白區(qū)和數(shù)據(jù)區(qū)。(1):頭指針(HostIndex)指向有數(shù)據(jù)區(qū)的頂部,每次寫入數(shù)據(jù),都更新頭指針,如果到了緩沖區(qū)的末端(EndIndex),就自動返回到緩沖區(qū)的起始處(StartIndex),直到寫入到尾指針處為止,這時(shí)緩沖區(qū)已經(jīng)被裝滿,不能再裝入數(shù)據(jù)。(2):尾指(TailIndex)針指向有數(shù)據(jù)區(qū)的尾部,當(dāng)數(shù)據(jù)發(fā)送完畢后,更新尾指針的位置,如果到了緩沖區(qū)的末端(EndIndex),就自動返回到緩沖區(qū)的起始處(StartIndex),直到遇到頭指針為止,這是證明所有的數(shù)據(jù)已經(jīng)發(fā)送完畢。串口2 (原文件名:串口2.J
7、PG) 這樣就實(shí)現(xiàn)了發(fā)送緩沖區(qū)的動態(tài)調(diào)整空白區(qū)和數(shù)據(jù)區(qū),剛剛發(fā)送完畢的數(shù)據(jù),馬上就被開辟出來用于存放下個(gè)數(shù)據(jù),最大可能的節(jié)省了寶貴的發(fā)送緩沖區(qū)的空間,提高了使用效率。 這個(gè)程序比較復(fù)雜,大致的流程如下(省略了狀態(tài)的判定,保護(hù)措施等代碼)程序段1-3/*將數(shù)據(jù)寫入發(fā)送緩沖區(qū)*/void USART1WriteDataToBuffer(*ptr,u8 count) while(count!='0') /*頭指針不等于尾指針,緩沖區(qū)沒有撐滿*/ if(USART1HosIndext!=USART1TailIndex) USART1SendTCBUSART1HosIndex=*ptr+
8、; /*更新頭指針,如果到了緩沖區(qū)的末端,就自動返回到緩沖區(qū)的起始處*/ if(+USART1HosIndext>=USART1_SEND_MAX_BOX)USART1HosIndext=0; /.判斷溢出等其他代碼省略./.發(fā)送中斷的ISR./void USART1SendUpdate(void) /*頭指針不等于尾指針,緩沖區(qū)尚有未發(fā)生完的數(shù)據(jù)*/ if(USART1HosIndext!=USART1TailIndex) /*將發(fā)送緩沖區(qū)的數(shù)據(jù)發(fā)送出去*/ USART1SendByte(*USART1TailIndex); /*更新尾指針的位置,如果到了緩沖區(qū)的末端,就自動返回到緩沖
9、區(qū)的起始處*/ if(+USART1TailIndex>=USART1_SEND_MAX_BOX)USART1TailIndex=0; /.判斷溢出等其他代碼省略./ 值得注意的是,一些微控制器中,例如在Cortex-M3的微控制器架構(gòu)中,有DMA傳送模式,可以配置一個(gè)內(nèi)部的通道,將指定的地址處的數(shù)據(jù),在無須CPU的管理下,直接將其發(fā)送到串口發(fā)送寄存器里去。通過這個(gè)方法,可以大大的降低了發(fā)送過程中重復(fù)進(jìn)入中斷的次數(shù),從而大大提高了效率。這樣,如果使用了這個(gè)芯片,就可以使用DMA模式進(jìn)行發(fā)送。但是DMA發(fā)送模式下,對于頭指針和尾指針就得做出一些修改,因?yàn)镈MA傳送過程中,是不能讓頭指針到達(dá)
10、緩沖區(qū)終點(diǎn)后,自動將指針調(diào)整到起點(diǎn)位置的。 但是,加入發(fā)送管理結(jié)構(gòu)體以后,上述問題可以得到解決。 利用內(nèi)存塊動態(tài)分配可以大大減少提高內(nèi)存的使用效率,尤其是對于串口通信而言,更是如此。利用內(nèi)存管理模塊可以將微控制器除全局變量和靜態(tài)結(jié)構(gòu)變量以外的剩余的內(nèi)存統(tǒng)一管理,在需要時(shí)候申請,在不用的時(shí)候釋放,如串口的發(fā)送緩沖區(qū),以太網(wǎng),SD卡,外部數(shù)據(jù)存儲器等等均可以用內(nèi)存來管理,可以重復(fù)使用,大大提高了使用效率。內(nèi)存分配1 (原文件名:內(nèi)存分配1.JPG) </center> 首先定義發(fā)送緩沖區(qū)管理塊的結(jié)構(gòu)體 typedef struct unsigned char Num; /該存儲區(qū)保存的
11、有效字節(jié)數(shù)量 unsigned char *Index; /該存儲區(qū)申請的內(nèi)存塊的指針 unsigned char *MemIndex; /該存儲區(qū)申請的內(nèi)存塊管理區(qū)的指針 USART1SendTcb; 例如需要200字節(jié):串口3 (原文件名:串口3.JPG) 這樣,加入動態(tài)內(nèi)存與發(fā)送緩沖區(qū)管理塊以后,無論是采用DAM模式發(fā)送數(shù)據(jù)還是普通的方式,都可以輕易的配置。將內(nèi)存塊的指針值Index傳給DMA的發(fā)送地址,將待發(fā)送的字節(jié)數(shù)Num傳給DMA的發(fā)送字節(jié)計(jì)數(shù)寄存器,就可以完成無須CPU管理的操作,最大的減少了CPU的使用,大大提高了內(nèi)存效率?;蛘卟捎闷胀ǖ闹袛嗄J?。 具體的代碼較長,見工程文件,
12、不再詳細(xì)列出。 內(nèi)存管理 在嵌入式設(shè)備中,往往會存在一些任務(wù)需要大量的內(nèi)存,在內(nèi)存相對較少的微控制器中,怎樣有效管理這些寶貴的資源,是必須解決的一個(gè)重要問題。 在上位機(jī)的編程中,我們通常使用malloc()函數(shù)以及Free()函數(shù)來完成對內(nèi)存的管理。這是因?yàn)橄鄬η度胧较到y(tǒng)而言,上位機(jī)的內(nèi)存非常大,而且Windows提供了很好的內(nèi)存管理接口,所以不存在問題。但是在嵌入式系統(tǒng)中,大量使用上述函數(shù)會出現(xiàn)兩個(gè)問題: (1)產(chǎn)生內(nèi)存碎片的問題。 在運(yùn)行的過程中,各個(gè)任務(wù)頻繁的調(diào)用內(nèi)存分配和釋放,會導(dǎo)致原本一整塊空間地址連續(xù)的區(qū)域分散成一堆物理地址上相互獨(dú)立的區(qū)域,這樣有可能導(dǎo)致一個(gè)程序需要一個(gè)較大的內(nèi)存
13、,空余的內(nèi)存塊沒有一個(gè)連續(xù)的地址,無法分配給任務(wù)。久而久之,最后系統(tǒng)可能連一個(gè)很小的物理地址都分配不到,最后導(dǎo)致系統(tǒng)的崩潰。如下圖所示:內(nèi)存分配2 (原文件名:內(nèi)存分配2.JPG) 在上圖中可以看到,雖然起始地址為20000的內(nèi)存區(qū)有16個(gè)空白的字節(jié),但是仍然無法為任務(wù)分配到四個(gè)字節(jié)的物理內(nèi)存。 (2)運(yùn)行的時(shí)間不確定的問題 在free()函數(shù)中,存在著一些內(nèi)存合并等功能,例如將釋放完成以后,將空間上相近的兩個(gè)空白區(qū)域合并為同一個(gè),將存在內(nèi)存碎片的區(qū)域重新整合,甚至可能使用了二叉樹等非線性數(shù)據(jù)結(jié)構(gòu),等等操作。 而這些函數(shù)所耗費(fèi)的時(shí)間是無法確定的,在實(shí)際的應(yīng)用中,對于內(nèi)存這種全局變量,多個(gè)任務(wù)都
14、要用到,為避免會存在可重入性的問題,必須采用信號同步的方法,或者暫時(shí)關(guān)閉中斷的方法,來同步對各個(gè)任務(wù)對共享資源的使用。這樣,導(dǎo)致了系統(tǒng)死區(qū)時(shí)間的增加,響應(yīng)速度的變慢,不確定性增加。 因此,在大多數(shù)嵌入式系統(tǒng)中,通常采用靜態(tài)內(nèi)存塊池的方法。將系統(tǒng)空余的內(nèi)存統(tǒng)一管理,生成一系列的大小固定的內(nèi)存塊池,在實(shí)際的操作中,以這一整個(gè)內(nèi)存塊進(jìn)行操作。 實(shí)現(xiàn)過程 首先定義內(nèi)存管理塊的結(jié)構(gòu)體 typedef struct OSMEMTCB void *OSMemFreeList;/用于指向該管理區(qū)中的空白的內(nèi)存塊 u8 OSMemBlkSize;/用于該管理區(qū)中的每個(gè)內(nèi)存塊的字節(jié)數(shù) u8 OSMemNBlks;
15、/用于該管理區(qū)中的分為多少個(gè)內(nèi)存塊 u8 OSMemFreeNBlks;/用于該管理區(qū)還剩多少空白內(nèi)存塊 OSMEMTcb; 將一個(gè)靜態(tài)的存儲區(qū)分配給內(nèi)存配置函數(shù),內(nèi)存管理塊的各個(gè)列表的含義如下圖所示:內(nèi)存分配3 (原文件名:內(nèi)存分配3.JPG) 每個(gè)內(nèi)存塊的頭四個(gè)字節(jié)用于存儲下一個(gè)內(nèi)存塊的指針地址,直到倒數(shù)第一個(gè)為止,最后一個(gè)指針指向一個(gè)空的指針,表明已經(jīng)到達(dá)內(nèi)存區(qū)的的末端。 在實(shí)際運(yùn)用過程中,OSMemFreeList是指向空白的內(nèi)存塊的指針,通過它來申請內(nèi)存,當(dāng)申請到內(nèi)存塊以后,OSMemFreeList指向當(dāng)前數(shù)據(jù)塊的下一個(gè)內(nèi)存塊節(jié)點(diǎn)地址(內(nèi)存管理函數(shù)已經(jīng)自動將所有內(nèi)存塊通過指針鏈接成
16、一個(gè)單向鏈表),當(dāng)釋放內(nèi)存塊的時(shí)候,將OSMemFreeList指向當(dāng)前釋放的內(nèi)存塊,將當(dāng)前內(nèi)存塊的下一個(gè)內(nèi)存塊指針指向先前的OSMemFreeList。OSMemFreeNBlks保存著該內(nèi)存區(qū)空白塊的數(shù)量,若內(nèi)存塊已滿,返回錯誤代碼,OSMemBlkSize指的是每個(gè)內(nèi)存塊內(nèi)字節(jié)數(shù)量,它的大小可以根據(jù)需要指定,理論上是它越小,內(nèi)塊的利用率就越高,例如保存一個(gè)101個(gè)字節(jié)的數(shù)據(jù),若一個(gè)內(nèi)存塊的大小是10個(gè)字節(jié),則需要11個(gè)內(nèi)存塊,若一個(gè)內(nèi)存塊的大小是100個(gè)字節(jié),則需要2個(gè)內(nèi)存塊,最后一個(gè)內(nèi)存塊僅僅使用了一個(gè)字節(jié)。但并非內(nèi)存塊的越小越好,因?yàn)楸4嫦聜€(gè)內(nèi)存塊節(jié)點(diǎn)的地址需要4個(gè)地址位,內(nèi)存塊越小
17、,保存地址的數(shù)據(jù)所占比例越高。在實(shí)際操作32字節(jié)過程中,可以定義大小不同的內(nèi)存塊,靈活運(yùn)用。內(nèi)存分配4 (原文件名:內(nèi)存分配4.JPG) 內(nèi)存配置函數(shù)的核心代碼:OSMemCreate(.)內(nèi)存分配5 (原文件名:內(nèi)存分配5.JPG) for(i=0;i<nblks-1;i+) plink=(void *)(link); /將二維指針定位到框的首位 *plink=(void *)(link+blksize); /該內(nèi)存塊的地址存放的 /是第二片內(nèi)存區(qū)的首地址 link+=blksize; /一維指針重新定位 /最后一個(gè)二維指針指向一個(gè)空指針 獲取內(nèi)存塊的核心代碼:OSMemGet(.)
18、tcb=(*ptr).OSMemFreeList; if(*ptr).OSMemFreeNBlks=0)return (void *)0;/如果空白內(nèi)存塊的數(shù)量為 /返回,若正確返回,收到的數(shù)據(jù)應(yīng)該是0 (*ptr).OSMemFreeNBlks-; /空白內(nèi)存塊塊數(shù)量減一 /空白內(nèi)存塊指針指向下一個(gè)內(nèi)存區(qū) /tcb指向的是內(nèi)存塊節(jié)點(diǎn)指針,不能直接使用,加上偏移值4個(gè)字節(jié) index=(u8 *)tcb; index+=4; /返回內(nèi)存塊指針 return index; 釋放內(nèi)存塊的核心代碼:OSMemDelete(.) (void *)tcb=(*ptr).OSMemFreeList; /將
19、OSMemFreeList重新指向這個(gè)已經(jīng)變成空白了的指針 (*ptr).OSMemFreeList=tcb; /將這個(gè)空白的指針的下個(gè)指針指向原先的空白區(qū)指針 (*ptr).OSMemFreeNBlks+; /空白內(nèi)存塊數(shù)量加1值得說明的是,工程文件中的OSQMem.h文件中OS_MEM_MAX /最多允許的內(nèi)存塊管理區(qū)OS_MEM_USART1_MAX 1024 /發(fā)送緩沖區(qū)的內(nèi)存大小OS_MEM_USART1_BLK 32 /每一個(gè)塊的長度 而 USART.h文件中DMA_MODE /定義是采用DMA模式,還是普通的中斷模式 推薦是用DMA模式再就是很多朋友可能覺得奇怪的是為什么一個(gè)是U
20、SART1.cUSART1Cinfig.cUSART1.c是上層文件,與硬件無關(guān),USART1Cinfig.c是底層文件,與硬件相關(guān),為了方便移植,只需改變USART1Cinfig.c的內(nèi)容就可以,我只有STM32的板子,Mega16的板子,和340的板子,都是我自己做的,這個(gè)程序經(jīng)過移植到上述三個(gè)板子以后已經(jīng)用在項(xiàng)目中了,在下是個(gè)菜鳥,希望朋友們多多指教。一直在這里學(xué)習(xí)到了很多東西,本人比較懶,老是索取而沒有回報(bào),希望能對初學(xué)的朋友們有用。我的郵箱是linquan315歡迎朋友們多多交流。2011年1月16日加上:在補(bǔ)上幾句話,告訴兄弟們怎么使用,把工程文檔的驅(qū)動這個(gè)文件夾的內(nèi)容加到你們的工程中就可以了,如果要使用
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度個(gè)人房屋裝修貸款合同模板8篇
- 2025年度城市更新項(xiàng)目土地使用權(quán)收購協(xié)議4篇
- 二零二五版貨運(yùn)車輛租賃合同示范文本(含實(shí)時(shí)跟蹤服務(wù))2篇
- 個(gè)人房屋建筑施工安全合同2024年度2篇
- 二零二五版虛擬現(xiàn)實(shí)(VR)教育培訓(xùn)服務(wù)合同
- 科學(xué)課堂上的商業(yè)思維啟蒙-小學(xué)案例分享
- 教育信息化與嵌入式技術(shù)的融合路徑
- 二零二五版?zhèn)€人獨(dú)資企業(yè)股權(quán)出售與競業(yè)禁止協(xié)議3篇
- 二零二五年度物業(yè)服務(wù)合同:某大型商場物業(yè)服務(wù)管理協(xié)議6篇
- 安裝購銷合同
- 2024年醫(yī)銷售藥銷售工作總結(jié)
- GB/T 44888-2024政務(wù)服務(wù)大廳智能化建設(shè)指南
- 2023-2024學(xué)年江西省萍鄉(xiāng)市八年級(上)期末物理試卷
- 四則混合運(yùn)算100道題四年級上冊及答案
- 四川省高職單招電氣技術(shù)類《電子基礎(chǔ)》歷年考試真題試題庫(含答案)
- 2024年江西生物科技職業(yè)學(xué)院單招職業(yè)技能測試題庫帶解析答案
- 橋本甲狀腺炎-90天治療方案
- (2024年)安全注射培訓(xùn)課件
- 2024版《建設(shè)工程開工、停工、復(fù)工安全管理臺賬表格(流程圖、申請表、報(bào)審表、考核表、通知單等)》模版
- 酒店人防管理制度
- 油田酸化工藝技術(shù)
評論
0/150
提交評論