STM32單片機一般少則3個串口,多則5個,而我這次的項目還偏偏5個硬件串口還是不夠用.
至于不夠用的原因,哎,是項目做到后面有定制,隨便哪個串口都省不得,沒得辦法,只能另想法子咯~
板子上有幾個預留IO口,可以用來模擬串口. 模擬串口一般都選9600,速度最快試了也才19200,
所以限制還是較多的,一般不得以情況下才會用到.
在寫程序之前我也是參考了前輩們,覺得寫的不咋地,照抄他的代碼,那我的系統(tǒng)啥事情也
不要干了,就在那里delay吧?。?! 模擬串口分收和發(fā):收比較難,發(fā)送比較容易,那就先將接收這塊吧。
接收:
有2種思路: 一種是第一個下降沿開始啟動定時器,每個bit都去采樣Rx電平;
從第一個邊沿開始統(tǒng)計時間戳,接收完10個bit后再解析.
我這邊碰巧選擇的是第二種方法,具體實現(xiàn)思路是:
① 啟動定時器2用來做背景時間,定時器分頻后的計數(shù)頻率為1MHz,那么對于9600bps來說1個bit就是104.16us,我們?nèi)≌麛?shù)104就可以了;
② 再同時啟動一個定時器3,定時時間為104*9.5,這個定時器中斷發(fā)生的時候表示一個字節(jié)接收完畢了;
我們以0x37串口通訊時序圖為例, ,傳輸?shù)臅r候是LSB 1st, Rx引腳選擇邊沿觸發(fā), 第1次邊沿到的時候啟動定時器2,同時啟動定時器3, 第2個邊沿的時候將定時器2的計數(shù)值存到數(shù)組里,此時是104,第3個邊沿觸發(fā)的時候將其計數(shù)104*5計數(shù)值,同理將4,5,6三個邊沿對應的TIM2值存到緩存里,最終是 0,104,416,520,728,936,除以104變成0,1,4,5,7,9;
如何將0,1,4,5,7,9解析成0x37,看似簡單的問題其實還是有點麻煩的~ 給個思路,先將0和9這樣的數(shù)字去掉,變成1,4,5,7;
然后從1開始數(shù)到8,跟數(shù)組里元素是否有匹配,如果匹配就將狀態(tài)取反,沒有就維持之前的狀態(tài):
1有,2,3沒有,4有,5有,6沒有,7有,8沒有-->11101100->倒序后就是0x37了;
再來分析幾個處理后的值:4,5,7: 1,2,3沒有,4有,5有,6沒有,7有,8沒有-->00010011->逆序后11001000->0xC8
1,2: 1有,2有,3,4,5,6,7,8沒有->10000000->逆序后00000001->0x01
1,2,3,4,6,7,8:1有,2有,3有,4有,5沒有,6有,7有,8有->10100101->逆序后10100101->0xA5
7,8:1,2,3,4,5,6沒有,7有,8有->00000010->逆序后01000000->0x40
總結下如果第一個是1開頭的那么得出的bit就是1,如果第一個是其他數(shù)字開頭的,則 "1到其他數(shù)字" 之間用0來填充;
下面我們就根據(jù)總結出來的規(guī)律編寫解析代碼:
int process_byte(int nums)
{
int i;
u8 a=0;
u8 byte=0;
u8 new_array[8];
memset(new_array,0,sizeof(new_array));
for(i=0;i<=nums;i++) //1...7
{
timerecode[i]+=ONE_BIT_TIME/2;
timerecode[i]/=ONE_BIT_TIME;
}
if(timerecode[nums]>=9) //計算下標是從1開始的,并且去掉了9,所以剩下的也不多了
nums--;
if(nums<=0) //全0特殊處理
return 0;
find_max=nums; //去掉第一個0
/*
假設收到的是0,2,4,9
經(jīng)過處理后就剩下2,4
將2放到new_array下標為1的地方,4放到下標為3的地方
*/
for(i=0;i { find_array[i]=timerecode[i+1]; if(find_array[i]!=0) { new_array[find_array[i]-1]=find_array[i]; } } /* 然后在for(i=find_array[0]-1;i<8;i++) 這個循環(huán)里找,如果對應的位有邊沿改變,就改變a的值 找不到就復制a的值,這里有點要注意,i循環(huán)是從高電平 開始的 */ for(i=find_array[0]-1;i<8;i++) { byte>>=1; if(i==new_array[i]-1) a=!a; if(a) byte|=0x80; } return byte; } 對于上圖0x37的例子,當定時器3中斷時,就調(diào)用process_byte(nums-1),其中nums=6,就 是邊沿次數(shù),來解析我們接收到的byte啦. 下面的截圖是我用模擬串口編寫的收發(fā)例子: 收發(fā)48個任意字節(jié)都正常,沒有哪個是解析錯的. 其他一些函數(shù)都比較簡單,建議大家自己動手! 有感興趣的,我會接著寫 模擬中斷發(fā)送!今天到此為止,希望各位喜歡~ 發(fā)送部分:這部分完全依賴定時器7了,定時周期104us。 發(fā)送的原理很簡單,我這里沒有使用delay方式來發(fā)送,而是在定時器里實現(xiàn)發(fā)送的; #define VIR_TXBUFF_SIZ 128 #define VIR_RXBUFF_SIZ 128 typedef struct { //---------Rx------------ u8 rxov; u8 rxlen; u8 rxbuff_idx; u8 rx_decode_flag; u8 RxBuff[VIR_RXBUFF_SIZ];//大小一定要是2的次方關系 u8 RXREG; //---------Tx------------ u8 send_flag; u8 send_max; u8 send_cnt; u8 send_mode; //0-阻塞式發(fā)送 1-中斷發(fā)送(放到sendbuff里,指定send_max即可) u8 sendbuff[VIR_TXBUFF_SIZ]; u8 TXREG; }VIRTUAL_UART_t; static u8 send_a_byte(u8 dat) { if(VirtualUart.send_flag) return 1; VirtualUart.TXREG=dat; TIM7->CR1 |= TIM_CR1_CEN; Tx_Pin=0; VirtualUart.send_flag=1; return 0; } static void send_remain_byte(void) { if(VirtualUart.send_cnt>=VirtualUart.send_max) { VirtualUart.send_flag=0; //發(fā)送完畢 } else { VirtualUart.TXREG=VirtualUart.sendbuff[VirtualUart.send_cnt++]; Tx_Pin=0; //產(chǎn)生START信號 } } //TIM7定時器里調(diào)用 static u8 tim_send_byte(void (*Callback)(void)) { static int sendidx=0; sendidx++; if(sendidx<=8) //DATA 1,2,3...8 { Tx_Pin=VirtualUart.TXREG&0x01; VirtualUart.TXREG>>=1; } else if(sendidx==9) { //STOP Tx_Pin=1; } else if(sendidx==10) { //STOP的發(fā)送完畢了 sendidx=0; if(Callback!=NULL) //有多個字節(jié)要發(fā)送,調(diào)用回調(diào)函數(shù)繼續(xù)發(fā)送下一個字節(jié) Callback(); else VirtualUart.send_flag=0; //已經(jīng)發(fā)送完畢了 return 0; } return 1; //1-busy } //阻塞式發(fā)送 void vu_send_string(u8 *s) { VirtualUart.send_mode=0; while(*s) { while(VirtualUart.send_flag!=0); send_a_byte(*s); s++; } } //阻塞式發(fā)送 void vu_send_len(u8 *s,int len) { VirtualUart.send_mode=0; while(len--) { while(VirtualUart.send_flag!=0); send_a_byte(*s); s++; } } //中斷發(fā)送 int vu_send_some_byte_noblock(int len) { if(VirtualUart.send_flag) return -1; if(len>VIR_TXBUFF_SIZ) return -2; VirtualUart.send_mode=1; VirtualUart.TXREG=VirtualUart.sendbuff[0]; TIM7->CR1 |= TIM_CR1_CEN; Tx_Pin=0; //產(chǎn)生START信號 VirtualUart.send_flag=1; VirtualUart.send_max=len; VirtualUart.send_cnt=1; return 0; } //主要發(fā)送部分代碼就在這兒了 void TIM7_IRQHandler(void) { TIM7->SR = (uint16_t)~TIM_IT_Update; if(VirtualUart.send_mode) { if(tim_send_byte(send_remain_byte)==0) { if(VirtualUart.send_flag==0) TIM7->CR1 &= ~TIM_CR1_CEN; TIM7->CNT=0; } }else { if(tim_send_byte(NULL)==0) { TIM7->CR1 &= ~TIM_CR1_CEN; TIM7->CNT=0; } } }
上一篇:關于stm32的GPIO的操作
下一篇:STM32 定時器周期動態(tài)修改
推薦閱讀
史海拾趣
進入21世紀后,F(xiàn)ox Electronics意識到全球化對于企業(yè)發(fā)展的重要性。為了更好地服務全球客戶,公司開始在全球范圍內(nèi)布局生產(chǎn)基地和銷售網(wǎng)絡。通過在亞洲、歐洲和北美等地設立分廠和辦事處,F(xiàn)ox Electronics不僅縮短了交貨周期,還降低了生產(chǎn)成本,提高了市場競爭力。同時,公司還加強了與全球供應鏈伙伴的合作,通過優(yōu)化供應鏈管理,確保產(chǎn)品質(zhì)量和交貨期的穩(wěn)定性。
隨著全球環(huán)保意識的提高和可持續(xù)發(fā)展的呼聲日益高漲,E-San Electronic Co Ltd積極響應這一趨勢,將環(huán)保和可持續(xù)發(fā)展理念融入企業(yè)的日常運營中。公司采用環(huán)保材料和節(jié)能技術生產(chǎn)電子產(chǎn)品,減少了對環(huán)境的污染和資源的浪費。同時,公司還積極參與各種環(huán)保公益活動和社會責任項目,為社會做出了積極的貢獻。這些舉措不僅提升了企業(yè)的社會形象和聲譽,也為企業(yè)贏得了更多消費者的信任和支持。
隨著公司實力的不斷增強,DACHANG公司開始積極拓展國際市場。公司參加了多個國際電子展覽會,與國際同行進行了廣泛的交流與合作。同時,DACHANG公司還積極尋求與國際知名企業(yè)的合作機會,不斷提升自己在全球電子產(chǎn)業(yè)鏈中的地位和影響力。
Comclok Inc創(chuàng)立之初,便專注于高精度時鐘芯片的研發(fā)與生產(chǎn)。在電子設備的智能化和精準化趨勢日益明顯的背景下,高精度時鐘芯片成為了市場的熱門需求。Comclok Inc憑借出色的技術實力和敏銳的市場洞察力,成功開發(fā)出一系列性能卓越的時鐘芯片,并迅速占領市場份額。公司不僅在國內(nèi)市場取得了成功,還積極拓展海外市場,與多家國際知名企業(yè)建立了長期合作關系。
ES Systems在創(chuàng)立初期主要面向高端市場提供定制化服務。然而,隨著市場競爭的加劇和客戶需求的變化,公司意識到必須調(diào)整市場策略。于是,ES Systems開始加大在中低端市場的投入,推出了一系列性價比高的產(chǎn)品。這一策略的調(diào)整使得公司的市場份額迅速擴大,同時也提高了品牌知名度。
為了更快地拓展市場,聚洵半導體積極尋求與國內(nèi)外知名企業(yè)的合作。公司與世界領先的芯片制造公司臺積電建立了晶圓代工合作關系,并在長電科技和華天科技進行封裝測試,確保了產(chǎn)品的一流工藝和品質(zhì)。此外,聚洵還與國內(nèi)多家電子元器件電商平臺如立創(chuàng)商城、華強芯城等建立了緊密的合作關系,通過線上線下雙管齊下的分銷渠道,將產(chǎn)品迅速推向市場。這些合作不僅提升了聚洵的品牌知名度,還極大地促進了其市場份額的增長。
1 引言 微通道板(MCP)是一種二維的電子倍增器,是微光像增強器的核心部件。用可溶性玻璃芯工藝制作微通道板,芯料玻璃在加工過程中僅起支撐作用,芯料的去除即腐蝕芯料工藝是微通道板制作關通常是將拋光好并洗凈的MCP半成品浸入溶解芯料玻 ...… 查看全部問答∨ |
|
流明學習筆記之一基本環(huán)境及HeLLo world 今天開始正式學習下流明,所用的環(huán)境當然MDK, 我想有幾個問題得明確下: 一,安裝MDK, 二,安裝流明的庫文件及例程,這個在TI網(wǎng)站上有的,各種器件的例程各庫都有,我用的是LM3S8962,所以我下個SW-EK-LM3S8962-8962.exe 或者 ...… 查看全部問答∨ |
|
在STM32上如何產(chǎn)生相同頻率不同相位的三相方波,要求頻率和相位均可調(diào),占空比固定50%。能否在TIM3上實現(xiàn)?… 查看全部問答∨ |
|
最近深入研究Linux內(nèi)核及各家芯片廠商提供的軟件方案,尤其是視頻類產(chǎn)品。 終于發(fā)現(xiàn)以前一個比較嚴重的問題的原因所在。 之前推廣TI DaVinci等產(chǎn)品時,發(fā)現(xiàn)ARM側的CPU戰(zhàn)用與代碼的真實吞吐量嚴重不對稱。 后來又有測試過多家的產(chǎn)品,包括國內(nèi)的一 ...… 查看全部問答∨ |
第一次燒寫2407的flash是成功了,但是,后來擦除就出現(xiàn)問題,現(xiàn)在再燒寫怎么也不成功了, **** Begin Sector Clear Operation **** OK: Flash Algorithm loaded into DSP memory OK: Write sector value 0x000f to symbol PRG_options OK: Set ...… 查看全部問答∨ |
要對一個0.5mv到5mv的信號進行積分放大,放大倍數(shù)40db以上,線性度要求1%以內(nèi),大神們能推薦一個積分放大器結構嘛?… 查看全部問答∨ |
設計資源 培訓 開發(fā)板 精華推薦
- IAR攜手極海半導體,高效開發(fā)全球首款基于Cortex-M52的G32R501實時控制MCU
- 迅為IMX6ULL開發(fā)板交叉編譯器的安裝和使用
- 迅為-i.MX6ULL 開發(fā)板-移植OpenCv3.4.1-搭建編譯環(huán)境
- 嵌入式學習篇丨迅為4412開發(fā)板Android4.4系統(tǒng)編譯
- Linux系統(tǒng)編程篇丨迅為IMX6ULL-對應視頻講解
- 嵌入式學習丨4412開發(fā)板-uboot源碼-匯編-源碼分析(一)嵌入式學習丨4412開發(fā)板-uboot源碼-匯
- 迅為IMX6ULL開發(fā)板-主頻和時鐘配置例程(二)
- 迅為IMX6ULL開發(fā)板-主頻和時鐘配置例程
- 迅為IMX6ULL開發(fā)板安裝VMware Tool工具
- 文遠知行采用BlackBerry QNX系統(tǒng),打造極致安全的ADAS解決方案
- IAR攜手極海半導體,高效開發(fā)全球首款基于Cortex-M52的G32R501實時控制MCU
- 中國發(fā)布HDMI和DisplayPort替代方案:GPMI接口來了
- 三星進軍 AI 機器人領域,Ballie 本周公開亮相
- 消息稱美光即日起針對存儲模組產(chǎn)品向美國客戶征收“關稅附加費”
- 迅為IMX6ULL開發(fā)板交叉編譯器的安裝和使用
- 迅為-i.MX6ULL 開發(fā)板-移植OpenCv3.4.1-搭建編譯環(huán)境
- BOE(京東方)董事長提議回購公司股份 堅定看好資本市場長期價值
- 英飛凌宣布收購Marvell的汽車以太網(wǎng)業(yè)務
- 強強聯(lián)合!兆易創(chuàng)新與納微半導體達成戰(zhàn)略合作