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

歷史上的今天

今天是:2025年01月21日(星期二)

正在發生

2020年01月21日 | STM8S003F使用IO口模擬串口(三)使用中斷方式發送和接收數據

發布者:溫柔浪漫 來源: eefocus關鍵字:STM8S003F  IO口  模擬串口  中斷方式  發送和接收數據 手機看文章 掃描二維碼
隨時隨地手機看文章

在前兩篇文章中我們介紹了IO口模擬串口發送數據和接收數據,前兩種方法都是使用定時器來進行發送和接收,沒有用到中斷,優點是邏輯簡單,但是缺點很明顯,只能進行單個字節的發送和接收,而且不能同時工作。因此在實際工程中沒有什么作用,僅供學習使用。使用中斷方式我們可以發送和接收多個字節的數據。


1、使用中斷方式進行IO口模擬串口發送和接收數據的原理

這篇文章我將使用中斷的方式進行發送和接收,同樣的,由于原理缺陷,這篇文章介紹的方法無法同時接收和發送,而且由于發送會延時,是一個不太好的方法,僅供學習使用。

注意:這篇文章實現的IO口模擬串口無法同時接收和發送數據!如有需要在實際項目中使用IO口模擬串口工作,請移步:


1.1、發送數據的原理

我們使用定時器更新中斷來進行數據的發送,首先在發送函數中開啟中斷,然后在中斷函數中逐位發送,直到發送10位(一個字節,我們暫時沒有使用校驗位)后關閉更新中斷。

1.2、接收數據的原理

我們使用單片機的外部中斷(IO中斷)來開啟比較中斷,在比較中斷中逐位接收,直到接收了10位后關閉比較中斷,并保存接收的有效字節個數。


2、實現過程

同樣的,在實現過程中,我們在工程文件夾SimUART中共分了4個文件夾(分別為System:存放系統文件;Project:存放項目文件;User:存放main.c和UserApp.c;My_Lib:存放其它常用的文件)。根據我們將用到的單片機的資源,我們在My_Lib中分了二個文件夾,分別是——IO:存放與IO口相關函數的文件;Time:與定時器和中斷相關函數的文件。下面我貼出相關函數的.c文件,而.h文件省略不寫,有需要的同學可以根據文章后面的網址下載使用。我的編程環境是IAR,需要自己建立IAR工程。下面詳細介紹(Project和System省略不寫,其中System只用了stm8s.h)。


2.1、一切從main()函數開始

同樣的,我們建立完工程后需要從main()函數開始,為便于理解,我將使用邏輯偽代碼,邏輯偽代碼如下:


int main( void )

{

單片機時鐘初始化;

IO口初始化;

定時器初始化;

中斷初始化;

while(1)

{

if( 需要發送的數據數 > 0 )

{

發送;

需要發送的數據數 = 0;

}

}

}


我們首先需要進行初始化的配置All_Config()【在UserApp.c中】,代碼如下:


//head file 

#include "UserApp.h"

#include "IO.h"

#include "User.h"

#include "Time.h"

#include "Delay.h"

 

u16 SimUART_SendData = 0xFF;

u8 SimUART_SendData_BitNum = 10;

u8  RxData_ValidNum = 0;

u16 RxDataValue_Temp = 0x0000;

 

//初始化函數

void All_Config( void )

{

    Clock_Config();

    IO_Init();  

    TIM2_Init();

    EXTI_Init();

}


其中User.h是我將自己常用的宏寫在了一個文件里面,對應于main.c。在沒有接外部時鐘的時候,STM8S003F在啟動時主時鐘默認為HSI RC時鐘的8分頻,我們這里的初始化僅指定為16MHZ高速內部RC振蕩器(HSI),也可以省略不寫,Clock_Config()【在UserApp.c中】函數代碼如下:


//初始化時鐘 選擇內部16M晶振

void Clock_Config()

{

    CLK->CKDIVR &= ~( BIT(4) | BIT(3) );

}


我選擇單片機的PD2作為我的模擬串口的數據發送口,選擇PD3作為我的模擬串口的數據接收口,IO_Init()【在IO.c中】函數代碼如下:

//head file

#include "IO.h"

#include "User.h"

 

void IO_Init()

{

    //TXD:TXD位推挽輸出  PD2

    SimUART_PORT->ODR |=  SimUART_PIN_TX; //0000 0100

    SimUART_PORT->DDR |=  SimUART_PIN_TX; //0000 0100

    SimUART_PORT->CR1 |=  SimUART_PIN_TX; //0000 0100  

    SimUART_PORT->CR2 &= ~SimUART_PIN_TX; //0000 0100

    

    //RXD:懸浮輸入 高電平 PD3

    SimUART_PORT->IDR |=  SimUART_PIN_RX; //0000 1000

    SimUART_PORT->DDR &= ~SimUART_PIN_RX; //0000 1000

    SimUART_PORT->CR1 &= ~SimUART_PIN_RX; //0000 1000

    SimUART_PORT->CR2 &= ~SimUART_PIN_RX; //0000 1000

}

其中在IO.h中的宏定義為:

//宏定義

#define SimUART_PORT GPIOD

#define SimUART_PIN_TX 0X04   //PD2

#define SimUART_PIN_RX 0X08   //PD3

#define SimUART_PIN_RX_0 0X00 //PD3

#define SimUART_PIN_RX_1 0X08 //PD3

定時器的初始化和前面一樣,具體操作可以見這里。代碼如下:

void TIM2_Init()

{

    CLK->PCKENR1 |= CLK_PCKENR1_TIM2; //使能 TIM2 

    TIM2->PSCR    = 0x04;                //16分頻 1MHZ 1us

    TIM2->ARRH    = ARRValue_9600 >> 8;  //自動裝載 每52us復位一次TIM2

    TIM2->ARRL    = ARRValue_9600;        //每1us遞減1

    TIM2->CNTRH = 0;              //定時器清零

    TIM2->CNTRL = 0; 

  

    TIM2->CR1 |= TIM2_CR1_CEN;    //開啟定時器

}

其中Time.h中的宏定義為:

#define ARRValue_9600   104

中斷初始化EXTI_Init()【在UserApp.c中】代碼如下:

//初始化中斷

void Interrupt_Init()

{

    //允許更新中斷

    //TIM2->CR1 &= ~TIM2_CR1_UDIS;      //允許更新  可以不管默認為0

    TIM2->IER |= TIM2_IER_UIE;          //更新中斷使能

 

    //IO口下降中斷 初始化

    SimUART_PORT->CR2 |= 0x08;          //使能外部中斷

    EXTI->CR1 = 0x80;                   //僅下降沿觸發    

 

    //禁止比較中斷

    TIM2->IER &= ~TIM2_IER_CC1IE;       //禁止捕獲/比較1

}

根據上面的原理,我們知道:更新中斷是在發送函數中打開的,因此更新初始化中使能;IO中斷是通過下降沿(串口數據的起始位為低電平)打開的,因此設置成使能和下降沿觸發;比較中斷實在IO中斷中打開的,因此設置成禁止。


2.2、模擬串口發送數據

完成時鐘、IO口、定時器、中斷的初始化以后我們就可以開始主體程序的設計了,邏輯偽代碼如下:


//發送 函數

void SimUART_SendByte(u8 SendData)

{

等待一個字節發送完畢;

第一步:清除 更新更新中斷標志位(保證不進入更新中斷);

第二步:數據調整(起始位為0,數據位不變,停止位和其它位為1);

第三步: 開啟更新中斷;

}

 

//定時器更新中斷  發送接收到的數據

#pragma vector = 對應向量標志位

__interrupt void SimUART_Update_IRQHandler(void)

{

第一步:清除 更新中斷標志位(保證不進入更新中斷);

發送一個位計數;

if( 發送位為1 )

{

發送高電平;

}

esle

{

發送低電平;

}

移位,發送下一個位;

//完成了一個位的發送

if( 發送了10個位 )

{

關閉中斷;

}

}


進入發送函數,首先應該清除更新中斷標志位,然后寫功能代碼,結束前需要打開更新中斷,從而去執行更新中斷的代碼。我們需要考慮為何需要一個延時來等待一個字節完成發送。在中斷函數中我們是讓一個字節發送完成以后才關閉中斷的,如果不延時,可能發生一個字節還沒有發送完成,卻進入下一個更新中斷的情況,因此需要等待,我們直接用一個標志位就能解決。對應向量標志位通過查芯片手冊和頭文件可以得到。發送函數在UserApp.c中,更新中斷在Time.c中,發送部分代碼如下:


void SimUART_SendByte(u8 SendData)

{   

    while( SimUART_SendData_BitNum < 10 );

    

    //清 更新中斷標志位

    TIM2->SR1 &= ~TIM2_SR1_UIF;

    

    //0000 0000 0000 0000 保證最低位(起始)為0,除數據位后全部為1

    SimUART_SendData = ( ( SendData << 1 )| (0xFE00) );

    SimUART_SendData_BitNum = 0;

    

    //開啟更新中斷

    TIM2-> IER |= TIM2_IER_UIE;    

}


//定時器更新中斷  發送接收到的數據

#pragma vector = TIM2_Updata_vector

__interrupt void SimUART_Update_IRQHandler(void)

{

    //第一步,清中斷標志位

    TIM2->SR1 &= ~TIM2_SR1_UIF;

    

    //發送一個位 計數

    SimUART_SendData_BitNum++;

    

    if( ((SimUART_SendData) & 0X0001) )  //如果是高電平,發高電平

    {

        SimUART_PORT->ODR |= SimUART_PIN_TX;

    }

    else                                        //如果是低電平,發低電平

    { 

        SimUART_PORT->ODR &= ~SimUART_PIN_TX;

    }

    

    //發送一個位 

    SimUART_SendData >>= 1;

        

    if( 10 <= SimUART_SendData_BitNum )

    {      

        TIM2-> IER &= ~TIM2_IER_UIE;

    }

}


2.3、模擬串口接收數據

接收字節也是一個字節一個字節的接收的,由于單片機的始終可能存在誤差(這是不可避免的),因此我們需要像個方法來除去這個誤差,我們可以增大采樣速度(減少采樣時間)來排除,比如:我采集5次(發送數據波特率為9600,采集就要是這個的5倍速度),如果有三個是高電平我們就認為該位是高電平。另一種方法是,我們讓采樣點始終在一個電平的中間,這就用到了IO中斷來開啟比較中斷。具體實現的邏輯偽代碼如下:


//接收數據

//判斷一個數據的開始  IO外部中斷

#pragma vector = 對應向量標志位

__interrupt void SimUART_IO_IRQHandler(void)

{

關閉 IO中斷 ;

設置 比較中斷 ;

清除 比較中斷 中斷標志位;

打開 比較中斷 ;

}

 

//接收數據  比較中斷

#pragma vector = 對應向量標志位

__interrupt void SimUART_Capture_IRQHandler(void)

{

清除 比較中斷 標志位;

接收位個數計數;

if( 接收位為1 )

{

將相應的位置1;

}

if( 接收了10個位 )

{

接收位個數清零;

關 比較中斷;

清除 IO中斷標志位;

開 IO中斷;

接收到的有效字節個數計數;

}

}

兩個中斷函數均在Time.c中,具體實現代碼如下:


//判斷一個數據的開始  IO外部中斷

#pragma vector = EXTI3_PD_vector

__interrupt void SimUART_IO_IRQHandler(void)

{

    //關閉IO中斷

    SimUART_PORT->CR2 &= ~0x08;

    

    //設置比較中斷

    TIM2-> CCMR1 &= 0x00;       //還是有問題

    

    //TIM2-> CCR1H = 0;

    TIM2-> CCR1L = TIM2->CNTRL + ( ARRValue_9600/2 );

    

    RxDataValue = 0x0000;

    //TIM2->CCER1 |= 0x00;

    TIM2->SR1 &= ~TIM2_SR1_CC1IF;  //清中斷標志位    

    TIM2->IER |=  TIM2_IER_CC1IE;  //使能 捕獲/比較中斷1  

}


//接收數據  比較中斷

#pragma vector = TIM2_Capture_vector

__interrupt void SimUART_Capture_IRQHandler(void)

{

    //第一步,清中斷標志位(防止始終進入中斷)

    TIM2->SR1 &= ~TIM2_SR1_CC1IF;  //清中斷標志位

    

    RxDataNum++;

    if( SimUART_PIN_RX_1 == (SimUART_PORT->IDR & SimUART_PIN_RX_1 ) )//其次,接收10個位

    {

        RxDataValue |= ( 0x01 << (RxDataNum) );//該位 置1       

    }

    

    //第二步,讀IO輸入     

    //首先,判斷是否接收了10個位             

    if(10 == RxDataNum)                 //如果是則

    {

        RxDataNum = 0;

        TIM2->IER &=  ~TIM2_IER_CC1IE;    //1、關 比較中斷

      

        //STM8S沒有外中斷標志位,STM8L有標志位,因此暫時不需要清中斷標志位

        SimUART_PORT->CR2 |= 0x08;        //2、開 IO中斷

        

        //處理有效數據

        if(  (RxDataValue & 0x0402) == 0x0400 )

        {

            RxDataValue_Temp = ( RxDataValue >> 2 );

            RxData_ValidNum++;//接收字有效 節數

        }

    }

}

2.4、補全main()函數

int main( void )

{

    All_Config();       //初始化

    _asm("rim");        //開總中斷

    

    while(1)           //發送循環

    {

        if( RxData_ValidNum > 0x00 )

        {

            SimUART_SendByte( RxDataValue_Temp );

            RxData_ValidNum = 0x00;

        }       

    }

    //return 0;

}


3、結束語

至此我們使用中斷的方法來進行IO口模擬串口(未使用庫函數)收發數據的功能已經實現,在本文章中,為了方便,我使用我的發送數據來驗證我接收數據的正確性,因此先寫的發送數據,再寫的接收數據。正如前面所說,我是一個位一個位的發送和接受,在發送過程中有發送延時,這樣的后果是如果是一個字符串的收發是沒問題的,但是由于沒有使用緩存區(即一個數組),導致我們收發數據不能分布于各個任務中,代碼在實際項目中可能會出現一些問題,例如已接受就得發送,否則會出現錯誤,這回影響單片機在執行任務時產生問題。我將在后面進行介紹我們在實際工程中能夠使用的全雙工串口程序。值得注意的是,收發應該是單獨存在的,我這里是為了方便反而讓我的發送程序發送接收到的數據。

[1] [2]
關鍵字:STM8S003F  IO口  模擬串口  中斷方式  發送和接收數據 引用地址:STM8S003F使用IO口模擬串口(三)使用中斷方式發送和接收數據

上一篇:STM8 IO口模擬串口通信
下一篇:【嵌入式開發】STM8S103F3P6單線半雙工串口通信

推薦閱讀

電子網消息,凱基證券分析師郭明錤19日下修2018年前兩季iPhone X出貨量,分別為1,800萬及1,300萬支。他更預期,iPhone X將在今年中結束生產,整個生命周期出貨量約6,200萬支,低于先前預估的8,000萬支,成為蘋果最短命的旗艦機種。但因蘋果已計劃下半年推出新款iPhone,價格降低又有新功能,他預期2018下半年才是真正需求爆發點,預估今年iPhone出貨年增...
電動汽車最為關鍵的部件之一,屬于動力電池,隨著動力電池密度的不斷提高,續航里程不斷的增加,越來越多的人關系動力電池的安全,目前應用于純電動汽車的動力電池主要有磷酸鐵鋰與三元鋰兩種,不管采用哪種都離不開鋰電,動力電池在車輛的工作過程中,電能一部分轉變為化學能,還用一部分轉變為熱能和其他能量。充電電池發熱屬于正常現象,但是涉及電池安...
狀態機的按鍵檢測思路2先回顧一下定義:狀態機有如下性質按鍵狀態機發生狀態遷移的條件如何準確檢測條件是否發生并進行狀態遷移確保狀態機能穩定地進行遷移按鍵消抖的原理:狀態切換按鍵操作觸發的時機先回顧一下定義:按鍵從未按下到按下,再到彈起,可以視為一個有4個狀態的有限狀態機。 分別是未按下、前沿抖動、按下、后沿抖動。 即按鍵只在這4個狀...
1月20日下午消息,雀巢中國與小米戰略合作今日正式開啟,雙方共同打造的雀巢健康管家“Nesfinity”正式發布。這標志著雙方從品牌合作正式跨入戰略合作。  雀巢健康管家是小米和雀巢聯手打造的智能營養和健康解決方案。這套體系覆蓋雀巢旗下全品牌種類優質健康食品,涵蓋專業營養知識,旨在滿足消費者人生全階段的不同健康管理需求。“雀巢健康...

史海拾趣

問答坊 | AI 解惑

如何優化單片機C語言代碼(程序員必讀)

如何優化單片機C語言代碼(程序員必讀) 1、選擇合適的算法和數據結構 ig 5Ce;P8R 應該熟悉算法語言,知道各種算法的優缺點,具體資料請參見相應的參考資料,有 Y YA/QLJ6 很多計算機書籍上都有介紹。將比較慢的順序查找法用較快的二分查找 ...…

查看全部問答∨

教你怎樣做好快速的嵌入式

怎樣做才能快速的嵌入式了? 其實,做工程是沒有捷徑可走的.聽聽下面一個大牛寫的! 先說做硬件: 把你的數字電路教材和模擬電路的教材讀熟,暫時先把重點放在數字電路上面,接著把微機原理和接口技術讀熟悉了,最好能用匯編寫幾個簡單的程序上機 ...…

查看全部問答∨

以后著地方一定要長來,著的資料很有價值.

以后著地方一定要長來,著的資料很有價值.現在用STM32在做項目了,以后希望大家能幫助,謝謝.…

查看全部問答∨

arm接口技術

最近開始學arm編程,覺得arm的接口技術很重要。 像中斷,RTC ,UART,SIO ,IIC等 這些東西把我搞的很暈,不知道具體從哪開始,一直看數據手冊那上面都是關于寄存器的知識,雖然記了但是還是不知道該從何做起。想做一個接口實驗,希望各位高手給以指 ...…

查看全部問答∨

STM32中斷優先級相關概念與使用筆記

一、基本概念 1.ARM cortex_m3內核支持256個中斷(16個內核+240外部)和可編程256級中斷優先級的設置,與其相關的中斷控制和中斷優先級控制寄存器(NVIC、SYSTICK等)也都屬于cortex_m3內核的部分。STM32采用了cortex_m3內核,所以這部分仍舊保留 ...…

查看全部問答∨

如何只用C語言,通過域名得到IP地址

請問各位高手,在一個單片機程序下,如何只用C語言,通過域名得到IP地址? 現在沒有DNS服務器,能通過GPRS進行網絡連接。…

查看全部問答∨

請教注冊表的一個問題

請教各位高手,注冊表[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\PCI\\VEN_1022&DEV_2000&SUBSYS_20001022&REV_10\\3&61aaa01&0&88]中3&61aaa01&0&88代表什么意思?謝謝!…

查看全部問答∨

WinCE上有現成的監控注冊表的類或方法嗎?

WinCE上有現成的監控注冊表的類或方法嗎?  當有改變時,應用程序可知道.…

查看全部問答∨

基于WINCE6.0 R3定制的模擬器NK能玩QQ但上不了網,為什么?Ping主機也是可以通的.

基于WINCE6.0 R3定制的模擬器NK能玩QQ但上不了網,為什么?Ping主機也是可以通的.…

查看全部問答∨

版主主:請教一個問題,謝謝!!

以前是用STM32F103V8的,這次我換成了STM32F103VB,買了30,可是出現問題了,共焊接了兩塊板,一塊板的晶振只會在偶爾上電時會起振(11.0592M),而另一塊板子可以起振,但程序跑起來不對,而我又把以前板子的STM32F103V8換到這塊板子上來又是好 ...…

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

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

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

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 汉中市| 海林市| 山东| 吐鲁番市| 桃园县| 忻城县| 甘南县| 阳东县| 绥德县| 张掖市| 秦皇岛市| 五河县| 武城县| 柳江县| 千阳县| 应用必备| 乌拉特前旗| 泽普县| 德江县| 海宁市| 嘉兴市| 开江县| 哈巴河县| SHOW| 子洲县| 麻栗坡县| 石屏县| 镇巴县| 通山县| 井冈山市| 鹰潭市| 仙居县| 白山市| 平泉县| 连山| 安西县| 沅江市| 漳浦县| 广平县| 洛隆县| 宝鸡市|