娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2025年01月31日(星期五)

2019年01月31日 | 基于STM32系列的模擬串口(非阻塞式)

發(fā)布者:工號待定 來源: eefocus關鍵字:STM32系列  模擬串口  非阻塞式 手機看文章 掃描二維碼
隨時隨地手機看文章

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系列  模擬串口  非阻塞式 引用地址:基于STM32系列的模擬串口(非阻塞式)

上一篇:關于stm32的GPIO的操作
下一篇:STM32 定時器周期動態(tài)修改

推薦閱讀

賓夕法尼亞、MALVERN — 2018 年 1 月30 日 — 日前,Vishay Intertechnology, Inc.(NYSE 股市代號:VSH)宣布,新推出電流達1A的集成式功率光敏可控硅---VO2223B,可直接驅動中功率的交流負載。Vishay Semiconductors VO2223B的dv/dt性能達到600V/μs,具有很高的穩(wěn)定性和噪聲隔離功能,可用于家用電器和工業(yè)設備。今天發(fā)布的這顆器件包括...
我下面要說的是基于stm32單片機的模擬IIC時序,以及是一些要注意的事項;結合自己所做的MMA7455加速度傳感器,我把模擬IIC的源代碼貼了出來,大家可以參考一下。1.因為在IIC協(xié)議中,當總線空閑的時候,SDA和SCL都為高電平,所以硬件電路中SDA和SCL引腳都要接上拉電阻。2.注意開始信號,停止信號,響應信號,非響應信號的時序,特別是要留意高低電平時間的...
追加數(shù)據(jù)的方法,最主要的是使用f_lseek函數(shù),但使用此函數(shù)時,我還是碰到不少的問題,現(xiàn)將自己在調(diào)試中碰到的事項分享給大家:1.為了追加數(shù)據(jù),必須獲取原文件的長度,可用f_size函數(shù),如下代碼:res = f_open(&fsrc, (const TCHAR *)DataFile, FA_OPEN_EXISTING | FA_READ);FileSize = f_size(&fsrc); 2.為了寫數(shù)據(jù),必須以寫的方式再打開一...
集微網(wǎng)1月30日消息,CUVA超高清視頻產(chǎn)業(yè)聯(lián)盟官方微博(以下簡稱官方)宣布了一則重磅消息,那就是國產(chǎn)視頻標準HDR Vivid正式商用,騰訊視頻將全球率先上線HDR Vivid內(nèi)容,華為手機也將首批支持該標準。 官方稱普通消費者可以通過騰訊視頻觀看采用HDR Vivid格式的高品質(zhì)影像內(nèi)容,這標志著CUVA聯(lián)盟的HDR Vivid技術正式進入商用階段。目前支持HDR Vivid...

史海拾趣

問答坊 | AI 解惑

微通道板腐蝕工藝研究

1 引言 微通道板(MCP)是一種二維的電子倍增器,是微光像增強器的核心部件。用可溶性玻璃芯工藝制作微通道板,芯料玻璃在加工過程中僅起支撐作用,芯料的去除即腐蝕芯料工藝是微通道板制作關通常是將拋光好并洗凈的MCP半成品浸入溶解芯料玻 ...…

查看全部問答∨

示波器使用中的常見問題

本人小小貢獻下,希望對大家能有點點幫助,有好東西一起分享交流!…

查看全部問答∨

討論:為避免跳槽失敗,增加跳槽的成功率,熱議一下注意事項

每一次跳槽意味著風險,可能跳槽失敗,也可能跳槽成功。為了提高跳槽成功率,大家熱議下關于跳槽需要考慮的那些問題?…

查看全部問答∨

流明學習筆記之一基本環(huán)境及HeLLo world

今天開始正式學習下流明,所用的環(huán)境當然MDK,   我想有幾個問題得明確下:   一,安裝MDK, 二,安裝流明的庫文件及例程,這個在TI網(wǎng)站上有的,各種器件的例程各庫都有,我用的是LM3S8962,所以我下個SW-EK-LM3S8962-8962.exe   或者 ...…

查看全部問答∨

如何產(chǎn)生三相同頻不同相位方波

                                 在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)的一 ...…

查看全部問答∨

新手提問:lf2407如何燒寫

第一次燒寫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),大神們能推薦一個積分放大器結構嘛?…

查看全部問答∨

TI接口指南

本帖最后由 dontium 于 2015-1-23 13:15 編輯 TI接口指南 …

查看全部問答∨
小廣播
設計資源 培訓 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 惠东县| 印江| 宝丰县| 龙口市| 宁夏| 雅安市| 安龙县| 丰原市| 瑞金市| 丰县| 宜都市| 丰原市| 密山市| 宜良县| 翼城县| 日喀则市| 鸡东县| 嘉善县| 富顺县| 赞皇县| 昌乐县| 汕头市| 定西市| 涪陵区| 鄂托克旗| 泰顺县| 仁怀市| 朝阳市| 汉源县| 集贤县| 军事| 三河市| 汪清县| 平果县| 房产| 剑河县| 石城县| 巴里| 滁州市| 沁阳市| 任丘市|