久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6173|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

基于STM32寄存器跑馬燈的實(shí)例講解

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:136256 發(fā)表于 2017-3-10 00:03 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
//======================================================//

**基于學(xué)習(xí)STM32有一段時(shí)間了,特意寫下一篇關(guān)于一個(gè)簡單的跑馬燈
的例程,梳理思路,也希望我自己的理解能幫到一些學(xué)習(xí)STM32的初學(xué)者
/**再此,鳴謝余師傅在學(xué)習(xí)上的大力幫助!!**/
//======================================================//

首先,GPIO的配置種類有8種。分別為模擬輸入、浮空輸入,上拉輸入、下拉輸入、開漏輸出、推挽輸出、復(fù)用開漏輸出、復(fù)用推挽輸出。
下面將以實(shí)例的方式講解GPIO的設(shè)置及實(shí)現(xiàn)過程。

事例1:跑馬燈實(shí)驗(yàn)
跑馬燈實(shí)驗(yàn)的功能:LED燈進(jìn)行有規(guī)律閃爍。(下面的LED燈的數(shù)量都為2個(gè),所以關(guān)于寄存器的配置也將以兩組的方式進(jìn)行講解)

首先要知道普通的IO就兩種功能一個(gè)為輸入,一個(gè)為輸出。然后再以輸入和輸出細(xì)分為以哪種模式輸出、以哪種模式輸入。要設(shè)置IO的模式這時(shí)就要使用到寄存器進(jìn)行設(shè)置,STM32的IO端口一般由7個(gè)寄存器來進(jìn)行控制。
分別為
(1)配置模式的2個(gè)32位的端口配置寄存器 CRL 和 CRH;
(2)2 個(gè) 32 位的數(shù)據(jù)寄存器 IDR 和 ODR;
(3)1 個(gè) 32 位的置位/復(fù)位寄存器BSRR;
(4)1個(gè) 16 位的復(fù)位寄存器 BRR;
(5)1 個(gè) 32 位的鎖存寄存器 LCKR;
而我們常用的 IO 端口寄存器只有 4 個(gè):CRL、CRH、IDR、ODR。

首先,一般一個(gè)程序的開始都會(huì)從入口main函數(shù)開始執(zhí)行,而一個(gè)功能的實(shí)現(xiàn)之前都需要做一些準(zhǔn)備工作,當(dāng)然跑馬燈也不例外,在程序執(zhí)行前,IO需要初始化,而初始化要做的就是對程序需要用到的GPIO的寄存器進(jìn)行配置。然后設(shè)定輸出設(shè)備的初始狀態(tài),即跑馬燈的初始狀態(tài)。一般程序在執(zhí)行前,輸出設(shè)備都會(huì)是處于關(guān)閉狀態(tài)。最后增加延時(shí)函數(shù),讓LED燈在亮與滅之間有一段時(shí)間的狀態(tài)保留,不然時(shí)間過快,人類的視覺根本捕抓它的狀態(tài)變化。

下面來講一下實(shí)現(xiàn)跑馬燈效果的IO要怎么配置。首先先說一下使用LED來進(jìn)行跑馬功能的話只需要用到RCC->APB2ENR、GPIOX->CRL、GPIOX->ODR三個(gè)寄存器(GPIOX中的X表示為GPIO的組別,例如GPIOB表示在GPIO的B組上,因?yàn)橐话銌纹瑱C(jī)上的GPIO一般都會(huì)有很多組的,這樣也只是為了區(qū)分這些IO罷了)
CRL 和 CRH 控制著每個(gè) IO 口的模式及輸出速率。

這里需要注意的是在配置GPIO前,都需要先使能該GPIO的時(shí)鐘!(可能有人會(huì)問“為什么一定要是使能時(shí)鐘呢?”答案是:GPIO也是外設(shè)的一種,然后外設(shè)是需要提供時(shí)鐘信號工作,以便于設(shè)置GPIO的數(shù)據(jù)傳輸速度的高速/低速輸出,所以有關(guān)數(shù)據(jù)的傳輸都是在時(shí)鐘信號的基礎(chǔ)上的。51單片的IO口也有時(shí)鐘,只是為了方便,默認(rèn)開啟的,ST的為了更好的控制功耗,電路上做的可以選擇開關(guān)時(shí)鐘,降低功耗。補(bǔ)充網(wǎng)友的答案:“寄存器是基于觸發(fā)器的,觸發(fā)器的賦值是一定需要時(shí)鐘的,而寄存器的時(shí)鐘是由總線時(shí)鐘提供的,就是說沒有總線時(shí)鐘的話,你給寄存器值它是不會(huì)讀入的”)
然后設(shè)置兩個(gè)LED的GPIO的模式,因?yàn)長ED是輸出設(shè)備,所以GPIO將設(shè)置成輸出模式,其中配置模式要用到的寄存器為配置寄存器CRL和CRH。其中CRH為高位寄存器,CRL為低位寄存器。(有人可能有疑問為什么用的是32位的寄存器為什么還要為兩個(gè)寄存器來管理呢?難道是32位還不夠配置嗎?答案是:是的,不夠用。配置寄存器對一個(gè)GPIO的配置要用4個(gè)位來完成。一組GPIO有16個(gè)引腳,一個(gè)引腳要4位的話,那么16個(gè)引腳就要16*4=64,那么就要2個(gè)32位的寄存器來實(shí)現(xiàn),所以就干脆把高八位給一個(gè)寄存器,低八位給另外一個(gè)寄存器,這就出現(xiàn)了CRL和CRH。也許有人還會(huì)有疑問說為什么一定要用4位來對一個(gè)引腳的配置呢?答案是肯定的,因?yàn)榍懊嬲f了,對GPIO的配置首先配置為輸入模式或者輸出模式,然后再對輸入、輸出配置為哪種輸出,哪種輸入,是推挽輸出呢,還是開漏輸入呢,這都是需要至少2個(gè)位來進(jìn)行配置,而且輸入、輸出模式各有4種模式,共8中,這樣要以最少的資源來實(shí)現(xiàn)的話,用00、01、10、11這種2個(gè)位來實(shí)現(xiàn)是最省資源的,所以2*2=4,所以對于1個(gè)GPIO的模式的配置至少也就要4位了。)
接著就是查看LED的GPIO的引腳接在IC哪個(gè)引腳上。怎么查看LED的引腳到底接在哪呢?這個(gè)要看開發(fā)板的原理圖,不同的板子來說或者對于不同的商家來說在GPIO的引腳接線上會(huì)有不同,以我的開發(fā)板的原理圖可以發(fā)現(xiàn)LED燈的GPIO分別接在了GPIOB的pin5和GPIOE的pin5上,根據(jù)電路性質(zhì),一般會(huì)將LED設(shè)置為推挽輸出模式(可能這時(shí)就會(huì)有人問了,為什么就是推挽呢?為什么不是開漏呢?我的理解是:這是有電路性質(zhì)決定的,推挽顧名思義就是灌電流與拉電流都可以輸出,通俗地講就是輸出高低電平。而開漏是一直輸出低電平,當(dāng)你要輸出高電平的時(shí)候需要加上拉)
通過查閱寄存器的數(shù)據(jù)手冊可知,00位通用推挽模式,那么
//======================================================//
GPIOB->CRL |= 3 << 20;//設(shè)置模數(shù)數(shù)據(jù)傳輸速率
GPIOB->CRL &=~(3 << 22);//設(shè)置GPIO模式
//======================================================//
這樣就把GPIOB組的pin5設(shè)置成了通用推挽模式,前面說了一個(gè)引腳需要4個(gè)位來配置,查看寄存器數(shù)據(jù)手冊可看到,前面2個(gè)位是設(shè)置通用推挽模式的,后面2個(gè)位是基于這種模式的數(shù)據(jù)傳輸速率,在這里我們懸著的是“最大速度50MHz”,而GPIOB->CRL|=3<<20;就是設(shè)置數(shù)據(jù)傳輸速率為最大速度50MHz,GPIOB->CRL&=~(3<<22);為設(shè)置GPIOB的pin5為通用推挽模式。

最后就是設(shè)置LED的初始狀態(tài)了,再說之前先說一下ODR寄存器。
ODR是一個(gè)端口輸出數(shù)據(jù)寄存器,也只用了低16位。該寄存器為可讀寫,從該寄存器讀出來的數(shù)據(jù)可以用于判斷當(dāng)前IO 口的輸出狀態(tài)。而向該寄存器寫數(shù)據(jù),則可以控制某個(gè) IO 口的輸出電平。
所以在配置LED初始化的時(shí)候就需要調(diào)用這個(gè)寄存器設(shè)置LED的初始狀態(tài)。
//======================================================//
GPIOE->ODR|=1<<5;//設(shè)置LED的初始化狀態(tài)為1(1為到電平,亮滅有其電路決定,我的開發(fā)板由于接了上拉,使得低電平才是有效的,即0為LED燈亮,1為LED燈滅)
//======================================================//
這樣初始化函數(shù)就完成了。

具體初始化代碼如下:
//=======================led.c===============================//
/**************************************************************
**為了使得程序的模塊化,所以把LED的初始化代碼獨(dú)立寫成一個(gè)源文件
**當(dāng)然這樣也使得需要寫一個(gè)頭文件進(jìn)行聲明,這樣才能讓main函數(shù)或者其他函數(shù)調(diào)用
**************************************************************/
#include "stm32f10x.h"
#include "led.h"

void led_Init(void)
{
        RCC ->APB2ENR |= 1 << 3;//使能 PORTB 時(shí)鐘
        RCC ->APB2ENR |= 1 << 6;//使能 PORTE 時(shí)鐘
        
        GPIOB ->CRL   |= 3 << 20;
        GPIOB ->CRL   &=~ (3 << 22);//PB.5 推挽輸出
        GPIOB ->ODR   |= 1 << 5;//PB.5 輸出高
        
        GPIOE ->CRL   |= 3 << 20;
        GPIOE ->CRL   &= ~(3 << 22);//PE.5 推挽輸出
        GPIOE ->ODR   |= 1 << 5;//PE.5 輸出高
}
//======================================================//

其頭文件如下:
//=========================led.h=============================//
#ifndef __LED_H_
#define __LED_H_

extern void led_Init(void);

#endif
//======================================================//

接下來說一下初始化好了,主函數(shù)要怎么寫。
第一需要的是點(diǎn)亮LED的語句,在初始化中有提到,設(shè)置LED初始化狀態(tài)即:GPIOB ->ODR   |= 1 << 5;//PB.5 輸出高
那么同時(shí)也能使用這句來進(jìn)行LED的亮滅控制。代碼如下:
//==========================main.c============================//
#include "stm32f10x.h"
#include "led.h"


int main(void)
{
                int i=0;
                led_Init();                //LED初始化
                while(1)
                {
                        
                        GPIOB ->ODR   &= ~ (1 << 5);        //PB.5輸出低電平,即點(diǎn)亮LED
                        GPIOE ->ODR   &= ~(1 << 5);         //PB.5輸出低電平,即點(diǎn)亮LED
                        for(i=0;i<1000000;i++);                        //延時(shí)

                        GPIOB ->ODR   |= 1 << 5;                //PE.5輸出高電平,即滅掉LED
                        GPIOE ->ODR   |= 1 << 5;                //PB.5輸出高電平,即滅掉LED
                        for(i=0;i<1000000;i++);                        //延時(shí)

                        
                }
}

//======================================================//
整個(gè)跑馬燈的工程就只需這三個(gè)文件,就能簡單實(shí)現(xiàn)跑馬的功能,如果你想要延時(shí)的時(shí)間是規(guī)律的,那么你就要去使用定時(shí)器了。因?yàn)槎〞r(shí)器定時(shí)的時(shí)間是準(zhǔn)時(shí)的,軟件延時(shí)第一消耗CPU的資源,然后時(shí)間也不夠精確,所以一般在對時(shí)間要求沒有很精確的要求是才會(huì)使用軟件延時(shí)的做法。

//=======================================================================//
注釋:1、如有錯(cuò)誤,跪謝大神出來指錯(cuò)。
          2、如這篇文章對您有些幫助,轉(zhuǎn)載請注明出處,謝謝!
//=======================================================================//

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:169653 發(fā)表于 2017-3-10 16:28 | 只看該作者
誒長號
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲精品第一 | 特级黄一级播放 | 高清国产一区二区 | 国产小视频自拍 | 自拍偷拍一区二区三区 | 51ⅴ精品国产91久久久久久 | 欧美中文字幕 | 久久久久久女 | 久久99精品久久久久久 | 中文字幕免费 | 一级做a爰片性色毛片 | 成人二区 | 日本成人中文字幕在线观看 | 91久久久久久久久久久 | 97伊人| 国产在线不卡视频 | av中文字幕在线观看 | 人人玩人人添人人澡欧美 | 天堂av影院| 久久久久国产精品 | 日本精品久久久久久久 | 日本a∨视频 | 日韩靠逼| 国产精品久久久久久中文字 | 久久成人精品 | 黄色大片免费观看 | 日韩在线小视频 | 日本一区二区三区免费观看 | 久色一区 | 日本精品视频 | 久久国产成人 | 男女羞羞的网站 | 日韩aⅴ视频| 国产一级片免费看 | 亚洲欧美激情精品一区二区 | 欧美电影在线观看网站 | 日韩欧美国产一区二区三区 | 欧美国产一区二区三区 | 三级免费| 手机看片在线播放 | 日本不卡视频 |