<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                【133.1 發送單字節的底層驅動函數。】 單片機內置的“獨立硬件串口模塊”能直接實現“發送一個字節數據”的基礎功能,因此,發送單字節的函數是應用層與硬件層的最小單位的接口函數,也稱為底層驅動函數。應用層再復雜的發送函數都基于此最小單位的接口函數來實現。單片機應用層與“獨立硬件串口模塊”之間的接口通信是靠寄存器SBUF作為中間載體的,要實現發送單字節的最小接口函數,有如下三個關鍵點。 第一個,單片機應用層如何知道“硬件模塊”已經發送完了一個字節,靠什么來識別?答:在初始化函數里,可以把“硬件模塊”配置成,每發送完一個字節后都產生一次發送中斷,在發送中斷函數里讓一個全局變量從0變成1,依此全局變量作為識別是否已經發送完一個字節的標志。 第二個,發送一個字節數據的時候,如果“硬件模塊”通訊異常,沒有按預期產生發送中斷,單片機就會一直處于死循環等待“完成標志”的狀態,怎么辦?答:在等待“完成標志”的時候,加入超時處理的機制。 第三個,在連續發送一堆數據時,如果接收方(或者上位機)發現有丟失數據的時候,如何調節此發送函數?答:可以根據實際調試的結果,如果接收方發現丟失數據,可以嘗試在每發送一個字節之后插入一個Delay延時,延時的時間長度根據實際調試為準。我個人的經驗中,感覺STM32這類M3核或者M4核的單片機在發送一個字節的時候只需判斷是否發送完成的標志位即可,不需要插入Delay延時。但是在其它某些個別廠家單片機的串口發送數據中,是需要插入Delay延時作為調節,否則在連續發送一堆數據時會丟失數據,這個,應該以實際調試項目為準。 片段的講解代碼如下: unsigned char Gu8ReceData; unsigned char Gu8SendByteFinish=0; //發送一個字節完成的標志 void usart(void) interrupt 4 //串口的中斷函數 { if(1==RI) { RI = 0; Gu8ReceData=SBUF; } else //發送數據引起的中斷 { TI = 0; //及時清除發送中斷的標志,避免一直無緣無故的進入中斷。 Gu8SendByteFinish=1; //從0變成1通知主函數已經發送完一個字節的數據了。 } } void UsartSendByteData(unsigned char u8SendData) //發送一個字節的底層驅動函數 { static unsigned int Su16TimeOutDelay; //超時處理的延時計時器 Gu8SendByteFinish=0; //在發送一個字節之前,必須先把此全局變量的標志清零。 SBUF =u8SendData; //依靠寄存器SBUF作為載體發送一個字節的數據 Su16TimeOutDelay=0xffff; //超時處理的延時計時器裝載一個相對合理的計時初始值 while(Su16TimeOutDelay>0) //超時處理 { if(1==Gu8SendByteFinish) { break; //如果Gu8SendByteFinish為1,則發送一個字節完成,退出當前循環等待。 } Su16TimeOutDelay--; //超時計時器不斷遞減 } //Delay();//在實際應用中,當連續發送一堆數據時如果發現丟失數據,可以嘗試在此增加延時 } 【133.2 發送任意起始位置任意長度的函數。】 要連續發送一堆數據,必須先把這堆數據封裝成一個數組,然后編寫一個發送數組的函數。該函數內部是基于“發送單字節的最小接口函數”來實現的。該函數對外通常需要兩個接口,一個是數組的任意起始位置,一個發送的數據長度。數組的任意起始位置只需靠指針即可實現。片段的講解代碼如下: //任意數組 unsigned char Gu8SendBuffer\[11\]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A}; //發送任意起始位置任意長度的函數 void UsartSendBuffer(const unsigned char \*pCu8SendBuffer,unsigned long u32SendSize) { static unsigned long i; for(i=0;i<u32SendSize;i++) //u32SendSize為發送的數據長度 { UsartSendByteData(pCu8SendBuffer\[i\]); //基于“發送單字節的最小接口函數”來實現的 } } void main() { UsartSendBuffer((const unsigned char \*)&Gu8SendBuffer\[0\],5);//從第0位置發送5個數據 UsartSendBuffer((const unsigned char \*)&Gu8SendBuffer\[6\],5);//從第6位置發送5個數據 while(1) { } } 【133.3 發送帶協議的函數。】 前面章節中,我們講過接收“帶固定協議”的程序框架,這類“帶固定協議”的數據串里本身就自帶了“數據的長度”,因此,要編程一個發送帶協議的函數,關鍵在于,在函數內部根據協議先提取整串數據的有效長度。該函數對外通常也需要兩個接口,一個是數組的起始位置,一個發送數據的最大限制長度。最大限制長度的作用是用來防止數組越界,增強程序的安全性。片段的講解代碼如下: //“固定協議”十六進制的數據格式:EB 01 00 00 00 0B 03 E8 00 01 0B 。其中: // EB是數據頭。 // 01是代表數據類型。 // 00 00 00 0B代表數據長度是11個(十進制)。 // 03 E8 00 01 0B代表其它數據 //“帶固定協議”的數組 unsigned char Gu8SendMessage\[11\]={0xEB,0x01,0x00,0x00,0x00,0x0B,0x03,0xE8,0x00,0x01,0x0B}; //發送帶協議的函數 void UsartSendMessage(const unsigned char \*pCu8SendMessage,unsigned long u32SendMaxSize) { static unsigned long i; static unsigned long \*pSu32; static unsigned long u32SendSize; pSu32=(const unsigned long \*)&pCu8SendMessage\[2\]; u32SendSize=\*pSu32; //從帶協議的數組中提取整包數組的有效發送長度 if(u32SendSize>u32SendMaxSize) //如果“有效發送長度”大于“最大限制的長度”,數據異常 { return; //數據異常,直接退出當前函數,預防數組越界 } for(i=0;i<u32SendSize;i++) //u32SendSize為發送的數據長度 { UsartSendByteData(pCu8SendMessage\[i\]); //基于“發送單字節的最小接口函數”來實現的 } } void main() { UsartSendMessage((const unsigned char \*)&Gu8SendMessage\[0\],100); //必須從第0位置發送 while(1) { } } 【133.4 程序例程。】 ![](https://img.kancloud.cn/57/01/57010762abae4157797b57319514eff1_468x181.png) 上圖133.4.1 232串口電路 程序功能如下: 單片機上電瞬間,直接發送三串數據。 第一串是十六進制的任意數據:00 01 02 03 04 第二串是十六進制的任意數據:06 07 08 09 0A 第三串是十六進制的“帶協議”數據:EB 01 00 00 00 0B 03 E8 00 01 0B 波特率9600,校驗位NONE(無),數據位8,停止位1。在電腦的串口助手軟件里,設置接收顯示的為“十六進制”(HEX模式),即可觀察到發送的三串數據。 代碼如下: \#include "REG52.H" void UsartSendByteData(unsigned char u8SendData); //發送一個字節的底層驅動函數 //發送任意起始位置任意長度的函數 void UsartSendBuffer(const unsigned char \*pCu8SendBuffer,unsigned long u32SendSize); //發送帶協議的函數 void UsartSendMessage(const unsigned char \*pCu8SendMessage,unsigned long u32SendMaxSize); void usart(void); //串口接收的中斷函數 void SystemInitial(void); void Delay(unsigned long u32DelayTime); void PeripheralInitial(void); unsigned char Gu8ReceData; unsigned char Gu8SendByteFinish=0; //發送一個字節完成的標志 //任意數組 unsigned char Gu8SendBuffer\[11\]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A}; //“固定協議”十六進制的數據格式:EB 01 00 00 00 0B 03 E8 00 01 0B 。其中: // EB是數據頭。 // 01是代表數據類型。 // 00 00 00 0B代表數據長度是11個(十進制)。 // 03 E8 00 01 0B代表其它數據 //“帶固定協議”的數組 unsigned char Gu8SendMessage\[11\]={0xEB,0x01,0x00,0x00,0x00,0x0B,0x03,0xE8,0x00,0x01,0x0B}; void main() { SystemInitial(); Delay(10000); PeripheralInitial(); //在此函數內部調用了發送的三串數據 while(1) { } } void usart(void) interrupt 4 //串口的中斷函數 { if(1==RI) { RI = 0; Gu8ReceData=SBUF; } else //發送數據引起的中斷 { TI = 0; //及時清除發送中斷的標志,避免一直無緣無故的進入中斷。 Gu8SendByteFinish=1; //從0變成1通知主函數已經發送完一個字節的數據了。 } } void UsartSendByteData(unsigned char u8SendData) //發送一個字節的底層驅動函數 { static unsigned int Su16TimeOutDelay; //超時處理的延時計時器 Gu8SendByteFinish=0; //在發送以字節之前,必須先把此全局變量的標志清零。 SBUF =u8SendData; //依靠寄存器SBUF作為載體發送一個字節的數據 Su16TimeOutDelay=0xffff; //超時處理的延時計時器裝載一個相對合理的計時初始值 while(Su16TimeOutDelay>0) //超時處理 { if(1==Gu8SendByteFinish) { break; //如果Gu8SendByteFinish為1,則發送一個字節完成,退出當前循環等待。 } Su16TimeOutDelay--; //超時計時器不斷遞減 } //Delay();//在實際應用中,當連續發送一堆數據時如果發現丟失數據,可以嘗試在此增加延時 } //發送任意起始位置任意長度的函數 void UsartSendBuffer(const unsigned char \*pCu8SendBuffer,unsigned long u32SendSize) { static unsigned long i; for(i=0;i<u32SendSize;i++) //u32SendSize為發送的數據長度 { UsartSendByteData(pCu8SendBuffer\[i\]); //基于“發送單字節的最小接口函數”來實現的 } } //發送帶協議的函數 void UsartSendMessage(const unsigned char \*pCu8SendMessage,unsigned long u32SendMaxSize) { static unsigned long i; static unsigned long \*pSu32; static unsigned long u32SendSize; pSu32=(const unsigned long \*)&pCu8SendMessage\[2\]; u32SendSize=\*pSu32; //從帶協議的數組中提取整包數組的有效發送長度 if(u32SendSize>u32SendMaxSize) //如果“有效發送長度”大于“最大限制的長度”,數據異常 { return; //數據異常,直接退出當前函數,預防數組越界 } for(i=0;i<u32SendSize;i++) //u32SendSize為發送的數據長度 { UsartSendByteData(pCu8SendMessage\[i\]); //基于“發送單字節的最小接口函數”來實現的 } } void SystemInitial(void) { unsigned char u8\_TMOD\_Temp=0; //以下是定時器0的中斷的配置 TMOD=0x01; TH0=0xfc; TL0=0x66; EA=1; ET0=1; TR0=1; //以下是串口接收中斷的配置 //串口的波特率與內置的定時器1直接相關,因此配置此定時器1就等效于配置波特率。 u8\_TMOD\_Temp=0x20; //即將把定時器1設置為:工作方式2,初值自動重裝的8位定時器。 TMOD=TMOD&0x0f; //此寄存器低4位是跟定時器0相關,高4位是跟定時器1相關。先清零定時器1。 TMOD=TMOD|u8\_TMOD\_Temp; //把高4位的定時器1填入0x2,低4位的定時器0保持不變。 TH1=256-(11059200L/12/32/9600); //波特率為9600。11059200代表晶振11.0592MHz, TL1=256-(11059200L/12/32/9600); //L代表long的長類型數據。根據芯片手冊提供的計算公式。 TR1=1; //開啟定時器1 SM0=0; SM1=1; //SM0與SM1的設置:選擇10位異步通信,波特率根據定時器1可變 REN=1; //允許串口接收數據 //為了保證串口中斷接收的數據不丟失,必須設置IP = 0x10,相當于把串口中斷設置為最高優先級, //這個時候,串口中斷可以打斷任何其他的中斷服務函數實現嵌套, IP =0x10; //把串口中斷設置為最高優先級,必須的。 ES=1; //允許串口中斷 EA=1; //允許總中斷 } void Delay(unsigned long u32DelayTime) { for(;u32DelayTime>0;u32DelayTime--); } void PeripheralInitial(void) { //發送任意數組 UsartSendBuffer((const unsigned char \*)&Gu8SendBuffer\[0\],5);//從第0位置發送5個數據 UsartSendBuffer((const unsigned char \*)&Gu8SendBuffer\[6\],5);//從第6位置發送5個數據 //發送帶協議的數組 UsartSendMessage((const unsigned char \*)&Gu8SendMessage\[0\],100); //必須從第0位置發送 }
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看