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

歷史上的今天

今天是:2025年04月18日(星期五)

2020年04月18日 | 單片機接收數據緩存的程序實現

發布者:平和寧靜 來源: eefocus關鍵字:單片機  接收數據  緩存 手機看文章 掃描二維碼
隨時隨地手機看文章

這兩天一直想著如何去實現一個串口接收緩存。試著用stm32的DMA去實現,但總是不是很方便,自己寫了個循環存儲的程序,但是總有些問題。今天看到網上的一段代碼,感覺自己寫的程序就是渣渣,瘋狂用條件判斷,但沒有將這種想法提升到數學方法的層次,只局限于描述現象。特將FIFO的代碼復制過來,供學習用。


由一個串口接收數據引發的問題與字節緩沖流系統的設計???????????
?
在一個wifi數據收發項目調試時發現,數據在高速連續發送和接收時,經常出現數據出現了丟失和系統的死機。單片機在接收串口數據時,傳統采用中斷方法或者查詢指定標志位方法接收數據。查詢指定標志位:這種方式通常在main函數的大循環中不斷的檢測標志位或者等待該標志位來判斷是否有數據接收。通常有兩種方式:??

1:在大循環中if(標志位成立)表明有數據接收?然后進行數據的處理。??
?
優點:不會引起整個main函數?線程的阻塞?;在簡單的數據接收項目中可以使用?
缺點:單片機一般都為單線程,復雜的控制中采用操作系統,例如UC/OS;所以,將所以都函數放在main函數大循環中進行輪番處理。整個循環周期時間不確定,其他任務函數可能發生阻塞,不能夠保證數據到來時,正好在執行檢測指定標志位,從而出現了數據丟失。

2:在大循環中 while(標志位);通過while來等待數據的到來。
優點:數據不會出現丟失,穩定。
缺點:整個main函數主線程出現堵塞,其他函數無法執行,上述所示。


顯然:以上兩種發送在復雜的控制系統中是不能采用的 ,因此:在沒有多任務操作系統時,數據的接收采用中斷接收的法式是最佳的。使用中斷,可以不用查詢和等待的方式接收數據,解決了許多問題。,此時,單片機可以說是多線程執行程序。main函數是一個線程,中斷服務子程序是一個線程。中斷是前臺,main函數是后臺。由于是多線程(一般而言),不得不考慮數據的安全性。中斷可能隨時到來。Main函數會隨時被打斷,程序計數器寄存器PC指針指向中斷函數入口地址,指向中斷函數。Main函數在處理數據時被打斷,可能會引發數據的丟失。共同訪問全局變量時,使用互斥信號量等一些手段保障數據不被修改。設計可能被中斷打斷的函數時,要注意函數的重入問題,像static等關鍵字。


字節接收緩沖系統設計的核心思想:
1:前臺(即中斷)負責接收數據,并不進行處理,將數據放入消息隊列中。
2:后臺(main函數)負責從消息隊列中取出消息,并處理。
3:整個接收系統核心為 隊列,可以當做緩沖區;遵循先進先出原則 FIFO
采用隊列方式接收數據比較簡單,并且實現了緩沖,不會出現數據的丟失。


消息隊列核心算法實現:


1:消息隊列核心數據結構
typedef struct Queue
{
unsigned char front; //隊列頭索引
unsigned char rear; //隊列尾索引
unsigned char *pArray;//簡易的隊列 指向數組
}QueueTypeDef;


2: 判斷隊列是否為滿偽算法
if( (rear + 1) % 數組的元素個數) == front)


3: 判斷隊列是否為空偽算法
if(rear == front)


4: 將數據加入隊列偽算法
if( 隊列不為滿 )
{
pArray[rear] = 數據;
rear = (rear + 1) % 數組的長度
}


5: 將數據從隊列中取出偽算法
if( 隊列不為空)
{
Val = pArray[front];
front = (front + 1 ) % 數組長度
}


以上是接收最簡單的一個字節的隊列;ASCII C 編譯通過 不依賴于單片機 ;將其加入中斷服務子程序中,把接收的數據加入隊列中;以stm32 單片機串口中斷為例:

void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)
{
USART_ClearITPendingBit(USART2,USART_IT_RXNE);


en_queue(&Queue,(uint8_t)USART_ReceiveData(USART2));  //將數據加入消息隊列中

}

if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET)       

{               

USART_ClearFlag(USART2,USART_FLAG_ORE);          

USART_ReceiveData(USART2); 

}

}


Main函數從消息隊列中取出數據
unsigned char val;
while(1)
{
if(out_queue(&Queue, &val)) //從隊列中取出數據
{
if(i == 16)
i=0;
LCD_print(1,i,val); //顯示取出的數據
i++;
}
….
……
//其他任務 …….
}


以上算法思路是以接收最簡單的一個字節為例:當然可以接收更復雜的數據,數據結構如下


typedef struct Message //消息數據結構
{
u8 clientID; //客戶端名
u8 messgeLength; //消息長度
u8 message_str[MessageSize]; //存放消息的數組
}MessageTypeDef;

typedef struct Queue //消息隊列 數據結構
{
u8 front; //隊列頭
u8 rear; //隊列尾 + 1


MessageTypeDef message[MessQueueSize]; //消息 


BOOL (*postMessage)(MessageTypeDef dat );   //消息進列 

BOOL (*getMessage)(MessageTypeDef * datAddr);//消息出列


}MessQueue;

MessageTypeDef;這個數據結構中 構造了接收數據的格式 并不是前面最簡單的一個字節,根據實際接收數據的需要來構造數據結構,當然在中斷函數中要進行數據的處理,也可以放在主函數中處理數據,中斷中依然是將字節放入消息隊列中。主函數處理完數據后在放入另一個消息隊列中,由其他函數處理數據,多級消息隊列。以下是帶特定格式的消息數據處理:
buff[buff_index] = USART_ReceiveData(USART2); //將接收的數據(1個字節)放入緩沖區
//
// if(buff[0] == 0x2B) //校驗數據頭
// {
// buff_index++;
// }
// else
// {
// buff_index = 0;
// }
//
// if(buff_index == 8) //獲取數據尾
// {
// length = (buff[7] - 0x30) + 1 + buff_index; // 計算數據尾索引
// }
//
// if(buff_index == length)
// {
// length = 200;
// buff_index = 0;
// receive = TRUE; //數據接收完成
// //DISABLE_WIFI_RX_IRQ(); //
// }


附: 字節緩沖流系統源碼:

文件 : queue.h

#ifndef QUEUE_H
#define QUEUE_H

#ifndef bool
#define bool unsigned char
#define true 1
#define false 0
#endif

#define QueueArraySize 32 //隊列長度 (字節)

typedef struct Queue
{
unsigned char front; //隊列頭
unsigned char rear; //隊列尾+1


unsigned char *pArray;  //指向字節數組 


}QueueTypeDef;

extern QueueTypeDef Queue;
extern unsigned char queueArray[QueueArraySize];

void queue_Init(QueueTypeDef *pQ, unsigned char *array); //初始化
bool full_queue(QueueTypeDef *pQ); //滿
bool emput_queue(QueueTypeDef *pQ); //空
bool en_queue(QueueTypeDef *pQ, unsigned char val); //入隊列
bool out_queue(QueueTypeDef *pQ, unsigned char *dat); //出隊列

#endif

文件:queue.c

#include “queue.h”

QueueTypeDef Queue;
unsigned char queueArray[QueueArraySize];

void queue_Init(QueueTypeDef *pQ, unsigned char *array)
{
Queue.front;
Queue.rear;


pQ->pArray = array;

pQ->front = 0;

pQ->rear = 0;


}
bool full_queue(QueueTypeDef *pQ)
{
if((pQ->rear + 1) % QueueArraySize == pQ->front)
return true;
else
return false;
}

bool emput_queue(QueueTypeDef *pQ)
{
if(pQ->front == pQ->rear)
return true;
else
return false;
}

bool en_queue(QueueTypeDef *pQ, unsigned char val)
{
if(full_queue(pQ))
{
return false;
}
else
{
*((pQ->pArray)+(pQ->rear)) = val;
//pQ->pArray[pQ->rear] = val;
pQ->rear = (pQ->rear + 1) % QueueArraySize;
return true;
}
}
bool out_queue(QueueTypeDef *pQ, unsigned char *dat)
{
if(emput_queue(pQ))
{
return false;
}
else
{
*dat = pQ->pArray[pQ->front];
pQ->front = (pQ->front + 1) % QueueArraySize;
return true;
}
}


附:復雜數據接收緩沖流實現

1:文件:queue.h

#ifndef QUEUE_H
#define QUEUE_H

#ifndef BOOL
#define BOOL unsigned char
#define TRUE 1
#define FALSE 0
#endif

#define MessageSize 10 //消息長度 (字節)
#define MessQueueSize 20 //隊列長度 sizeof( MessageTypeDef)

typedef unsigned char u8;
typedef unsigned int u16;

typedef struct Message //消息數據結構
{
u8 clientID; //客戶端名
u8 messgeLength; //消息長度
u8 message_str[MessageSize]; //存放消息的數組
}MessageTypeDef;

typedef struct Queue //消息隊列 數據結構
{
u8 front; //隊列頭
u8 rear; //隊列尾 + 1

MessageTypeDef message[MessQueueSize]; //消息 


BOOL (*postMessage)(MessageTypeDef dat );   //消息進列 

BOOL (*getMessage)(MessageTypeDef * datAddr);//消息出列


}MessQueue;

extern MessQueue mess_queue;

void MessageQueueInit(void); //初始化
BOOL full_queue(void) ;//判斷是否為滿
BOOL emput_queue(void);//判斷是否為空
BOOL en_queue(MessageTypeDef message) ;//入列
BOOL out_queue(MessageTypeDef *message); //出列

#endif

2:文件:queue.c

#include “queue1.h”

MessQueue mess_queue; //定義消息隊列

void MessageQueueInit(void) //初始化
{
mess_queue.front = 0;
mess_queue.rear = 0;
mess_queue.postMessage = en_queue;
mess_queue.getMessage = out_queue;
}

BOOL full_queue(void) //判斷隊列是否為滿
{
if( (mess_queue.rear + 1) % MessQueueSize == mess_queue.front ) // rear + 1 = front
{
return TRUE;
}
else
{
return FALSE;
}
}

BOOL emput_queue(void) //判斷隊列是否為空
{
if(mess_queue.front = mess_queue.rear) //front = rear
{
return TRUE;
}
else
{
return FALSE;
}
}

BOOL en_queue(MessageTypeDef message) //入列
{
if(full_queue()) //判斷隊列是否為滿
{
return FALSE;
}
else
{
u8 i = 0;


(&(mess_queue.message[mess_queue.rear]))->clientID = message.clientID;

(&(mess_queue.message[mess_queue.rear]))->messgeLength = message.messgeLength;


for(i=0; i<(message.messgeLength); i++)

{

(&(mess_queue.message[mess_queue.rear]))->message_str[i] = message.message_str[i];

}

mess_queue.rear = (mess_queue.rear + 1) % MessQueueSize;

return TRUE;


}

BOOL out_queue(MessageTypeDef *message) //出列
{
if(emput_queue()) //判斷是否為空
{
return FALSE;
}
else
{
u8 i;
message->clientID = (&(mess_queue.message[mess_queue.front]))->clientID;
message->messgeLength = (&(mess_queue.message[mess_queue.front]))->messgeLength;


for(i=0; i<(message->messgeLength); i++)

{

message->message_str[i] = (&(mess_queue.message[mess_queue.front]))->message_str[i];

}


mess_queue.front = (mess_queue.front + 1) % MessQueueSize;

return TRUE;

}


}

完! 以上為整個數據接收的核心算法 在ASCII C編譯器上編譯通過,不依賴于底層。移植時修改相應的數據類型。

關鍵字:單片機  接收數據  緩存 引用地址:單片機接收數據緩存的程序實現

上一篇:stm32驅動Lora串口模塊
下一篇:stm32l0 rtc休眠周期自動喚醒文檔整理

推薦閱讀

(北京,2018年4月17日) 今天,致力于提供異構計算加速整體解決方案、業界領先的異構加速和業務卸載方案廠商——杭州加速云信息技術有限公司(簡稱:加速云)正式啟動跨越北京、上海、成都、西安四大城市的 “加速新科技,驅動智未來” 科技峰會暨新產品發布會。在發布會上,加速云隆重發布四大創新產品及三大解決方案,并邀請Intel和Cytech專家分享工業...
高通與蘋果宣布和解:放棄全球范圍內所有訴訟,并達成一系列合作。高通與蘋果的和解,固然雙方都會受益,但高通更是勝利者。 面對蘋果這樣的“超級甲方”,許多公司都以進入蘋果供應鏈為榮。而如果與蘋果交惡,短則業績大幅下降,長則公司前景黯淡。此前Imagination和Dialog等芯片公司均因被蘋果“拋棄“而“沒落”。但高通不僅能夠跟蘋果分庭抗禮,最終還...
1.內存接口介紹1.1.內存控制器的引入1.1.1 引入2440是一個SOC,其中外設分為多種類型:門電路類:GPIO協議類接口: UART I2C SPI內存類設備:nor flash ,SDRAM,NET DM9000但是對于CPU來說,并不直接控制外設,只需要將值寫給相關外設模塊的寄存器,CPU通過地址來區分不同的寄存器,因此就需要引入另一個控制單元——內存控制器。除NAND外,以上外設都...
昨天,索尼發布了新的 Xperia 1 III 和 5 III 旗艦設備。今天,該公司在微博上確認了新設備在中國市場的發布日期。根據官方消息,索尼將于 5 月 20 日將 Xperia 1 III 帶到中國市場。價格和其他信息將在 5 月 20 日的新聞發布會上披露。索尼 Xperia 1 III 配備 6.5 英寸的 4K OLED HDR FHD+ 120Hz 屏,搭載高通驍龍 888 ...

史海拾趣

問答坊 | AI 解惑

電子設計工程常用應用問答20篇. 下

電子設計工程常用應用問答20篇.   下    上下一起下才可以用!…

查看全部問答∨

揭秘:RF頻譜中的干擾問題

在網絡管理員努力理解 RF 頻譜中的干擾問題時,他們會聽到有關干擾對無線網絡的影響的傳言。      此白皮書幫助揭密網絡管理員在探索干擾問題時遇到的 10 大傳言。   作為一名網絡管理員,您關心 WLAN 的性能。您希望優化其性能以 ...…

查看全部問答∨

wince 觸摸屏感覺進不了中斷

最近一直調試觸摸屏問題,有些ddsi函數也能執行, touch.dll也能被調用,但是就是點擊觸摸屏沒有反應,感覺中斷進不去呢,有懂觸摸屏 驅動的朋友嗎?感謝給與解答,多謝了!…

查看全部問答∨

如何改變wince文件對話框的大小?

wince的filedialog默認全屏顯示,而文件列表卻很小,請問如何改變?…

查看全部問答∨

關于超寬帶UWB無線收發模塊

各位,有沒有做過超寬帶項目的,想咨詢一下關于超寬帶無線收發模塊的產品,現在還有哪些國內能弄到的?謝謝啦!…

查看全部問答∨

哪位高手能給我一下這個芯片的資料.謝謝

哪位高手能給我一下這個TLV320AIC23芯片的資料.謝謝…

查看全部問答∨

防止沉水貼:新制作之——筆筒式萬年歷

近段時間確實有點賴: 看圖,說話! 詳細:http://hi.baidu.com/haorongwu/bl ... Stamp=1301570434921 (內有清晰視頻。。嘻嘻。。。賴人。。。 )…

查看全部問答∨

MSP430的功耗問題。

datasheet里面的Iam Active Mode Supply Current Into VCC Excluding External Current是不是沒有包括輸出?最差的情況下Iam也只有幾個mA,幾個管腳的拉電流加起來都不止了吧?…

查看全部問答∨

串口與modem流量控制大全(2)

PC端處理:      本端發送            當 發現(不一定及時發現) CTS (-3V to -15V)無效時,停止發送,            當 發現(不一定及時 ...…

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

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 苏尼特右旗| 巴林左旗| 维西| 武夷山市| 阿克陶县| 泗水县| 多伦县| 遂溪县| 东光县| 什邡市| 建平县| 澄迈县| 望奎县| 仪陇县| 五寨县| 广德县| 射洪县| 孟连| 手游| 英吉沙县| 土默特左旗| 洛阳市| 金昌市| 桦甸市| 盐源县| 静乐县| 连南| 仙游县| 金门县| 新兴县| 额尔古纳市| 泾川县| 喀喇沁旗| 门头沟区| 保德县| 南木林县| 图木舒克市| 新巴尔虎左旗| 云龙县| 蒲城县| 西峡县|