看朱老師的視頻,一點點記錄
1 LED硬件工作原理及原理圖查閱(硬件有關)
1.1 原理圖是在底板x210bv3中查詢
查閱原理圖,發現開發板上一共有5顆LED。其中一顆D26的接法是:正極接5V,負極接地。因此這顆LED只要上電就會常亮。因此我們分析這顆LED是電源指示燈。
剩下4顆LED的接法是:正極接3.3V,負極接了SoC上的一個引腳(GPIO),具體詳細接法是:
D22:GPJ0_3
D23:GPJ0_4
D24:GPJ0_5
D25:PWMTOUT1(GPD0_1) [PWMTOUT1接在了核心板x210cv3,利用好pdf 閱讀器中的搜索功能]
1.2 分析如何點亮及熄滅LED(GPIO)
分析:LED點亮的要求是:正極和負極之間有正向電壓差。
思考:在開發板上如何爲LED製造這個電壓差讓它點亮呢?
解答:因爲正極已經定了(3.3V),而負極接在了SoC的引腳上,可以通過 SoC中編程來控制負極的電壓值,因此我們可以通過程序控制負極輸 出低電平(0V),這樣在正負極上就有了壓差,LED即可點亮。
數據手冊查閱及相關寄存器瀏覽
2.1 GPIO概念的引入
GPIO:general purpose input output 通用輸入輸出
GPIO就是芯片的引腳(芯片上的引腳有些不是GPIO,只有一部分是),作爲GPIO的這類引腳,他的功能和特點是可以被編程控制它的工作模式,也可以編程控制他的電壓高低等。
通過之前的分析我們知道,我們設計電路時就把LED接在了一個GPIO上,這樣我們就可以通過編程控制GPIO的模式和輸入輸出值來操控LED亮還是滅;如果你當時設計電路時把LED接在非GPIO上那就不可能了。
2.2 閱讀數據手冊中有關部分(S5PV210_UM_REV1.1)
當我們想要通過編程操控GPIO來操作LED時,我們首先需要通讀一下S5PV210的數據手冊中有關於GPIO的部分,這部分在數據手冊的Section2.2中。
GPJ0CON[0] 就是GPJ0CON_0
[3:0] —— bit3 ~ bit0 4位
bit3 ~ bit0,設置的不同分別有7種模式
2.3 GPIO相關的寄存器介紹
回憶下之前說過的,軟件操作硬件的接口是:寄存器。
我們當前要操作的硬件是LED,但是LED實際是通過GPIO來間接控制的,所以當前我們實際要操作的設備其實是SoC的GPIO。要操作這些GPIO,必須通過設置他們的寄存器。
查閱數據手冊(S5PV210_UM_REV1.1)可知,GPJ0相關的寄存器有以下:
GPJ0CON, (GPJ0 control)GPJ0控制寄存器,用來配置各引腳的工作模式
GPJ0DAT, (GPJ0 data)當引腳配置爲input/output模式時,寄存器的相 應位和引腳的電平高低相對應。
GPJ0PUD, (pull up down)控制引腳內部弱上拉、下拉
GPJ0DRV, (driver)配置GPIO引腳的驅動能力
GPJ0CONPDN,(記得是低功耗模式下的控制寄存器)
GPJ0PUDPDN (記得是低功耗模式下的上下拉寄存器)
注:在驅動LED點亮時,應該將GPIO配置爲output模式。
實際上真正操控LED的硬件,主要的有:GPJ0CON, GPJ0DAT 這麼2個。
如何點亮LED,編程的步驟是:
1、操控GPJ0CON寄存器中,選中output模式
2、操控GPJ0DAT寄存器,相應的位設置爲0
3.從零開始手寫彙編點亮LED
3.1 GPxCON、GPxDAT寄存器分析
GPJ0端口一共有8個引腳,分別記住:GPJ0_0 ~ GPJ0_7,相關重要寄存器就是GPJ0CON和GPJ0DAT
GPJ0CON寄存器中設置8個引腳的工作模式(32/8=4,每個引腳可以分到4位,譬如GPJ0_0對應的bit位爲bit0~bit3,GPJ0_3對應的位爲bit12~bit15。工作方法是:給相應的寄存器位寫入相應的值,該引腳硬件就會按照相應的模式去工作。譬如給bit12~bit15寫入0b0001,GPJ0_3引腳就成爲輸出模式了)
3.2 從零開始寫代碼操作寄存器
需要哪些先決條件才能寫呢?
1. 硬件接法和引腳:GPJ0_3 GPJ0_4 GPJ0_5 低電平亮/高電平滅;
2. GPJ0CON(0xE0200240)寄存器和GPJ0DAT(0xE0200244)寄存器;
3. 工程管理:Makefile等。
根據以上分析,我們就知道代碼的寫法了,代碼所要完成的動作就是:
把相應的配置數據寫入相應的寄存器即可。
3.3 怎麼寫?
先將朱老師寫好的led文件(1.leds_s)中的 三個文件(Makefile、mkv210_image、write2sd)複製到自己的文件夾(2.leds_s)裏,然後新建一個.S文件(led.S),在這個文件裏寫程序。具體的程序怎麼寫、爲什麼這麼寫,在這個文件後面都有註釋。
3.4 編譯、下載、運行看結果
編譯時用我們的工程管理,直接make編譯得到led.bin和210.bin
下載運行可以用usb啓動dnw下載;也可以用sd卡燒錄下載,根據自己的情況用一般都用usb下載,因爲方便。用usb啓動dnw下載,則運行led.bin文件
注意:開發板上按下電源鍵之後4顆LED默認都是半亮的,當我們下載程序後其中3顆變的很亮,這說明我們的程序已經運行了。
3.5 總結和回顧(軟件控制硬件思想、寄存器意義、原理圖數據手冊的作用)
軟件到底是怎麼控制硬件的?爲什麼程序一運行硬件就能跟着動?
軟件編程控制硬件的接口就是:寄存器
4.問題及解決
問題1 後綴名沒改
應該創建文件名爲2.leds_s.S ,而我創建爲2.leds_s.S.txt。
問題2 不細心
編程的時候把r0寫成了ro 。
問題3 編譯得到led.bin和210.bin,運行哪一個?
用usb啓動dnw下載,則運行led.bin文件;
用sd卡燒錄下載,則運行210.bin文件。
5 程序分析
目的:讓3個LED(GPJ0_3、GPJ0_4、GPJ0_5)全亮。(2.leds_s)
第一步:把0x11111111寫入0xE0200240(GPJ0CON)位置。
原因: 應該將GPJ0_3、GPJ0_4、GPJ0_5這3個引腳設置爲輸出模式,其餘5個引腳無所謂,故乾脆把8個引腳(GPJ0CON_0~GPJ0CON_7)全設置爲輸出模式。
第二步:把0x0寫入0xE0200244(GPJ0DAT)位置。
原因: 實際上只需要將GPJ0DAT的8個bit中的bit3—bit5設置爲0,其餘 bit位是0是1無所謂,所以乾脆都設置爲0,即00000000,即0x0。
6.問題提出:如何只點亮中間1顆(兩邊是熄滅的)LED(3.leds_s)
分析: 程序其實就是寫了GPJ0CON和GPJ0DAT這2個寄存器而已,功能更 改也要從這裏下手。GPJ0CON寄存器不需要修改,GPJ0DAT中設置 相應的輸出值即可。
直接解法: GPJ0DAT = 0x28 代碼見<3.led_s>
目的:只讓中間的LED(GPJ0_4)亮,另外兩個(GPJ0_3、GPJ0_5)熄。
程序分析:
第一步:把0x11111111寫入0xE0200240(GPJ0CON)位置。把8個引腳全設置 爲輸出模式,代碼不變
第二步:把0x28寫入0xE0200244(GPJ0DAT)位置。
原因: 將GPJ0DAT的8個bit中的bit4設置爲0,bit3和bit5爲1,其餘幾 位是0是1無所謂(因爲我只需要用bit3,bit4,bit5),那我就將 其餘幾位都設置爲0,即00101000,即0x28。
小結: 1.這樣寫可以完成任務。
2.這樣寫有缺陷。缺陷就是需要人爲的去計算這個特定的設置值,而 且看代碼的也不容易看懂。
解決方案:在寫代碼時用位運算去讓編譯器幫我們計算這個特定值。
7.使用位運算實現功能
7.1常用位運算:位與(&) 位或(|) 位非(取反 ~) 移位(左移<< 右移>>)
7.2 目的: 中間亮兩邊滅
直接解法: GPJ0DAT = 0x28
位運算: ldr r0, = ((1<<3) | (1<<5))
分析: 1左移3位爲1000,1左移5位爲100000,1000和100000進行位或 運算,得到0b00101000,即0x28
0b00101000 // 在00101000前面加個0b,代表00101000是二進制。
還可以這樣,ldr r0, = ((1<<3) | (0<<4) | (1<<5))
別人一看就知道,哪個亮哪個滅,bit3和bit5滅,bit4亮
7.3 擴展一下:如何只熄滅中間1顆而點亮旁邊2顆
ldr r0, = ((0<<3) | (1<<4) | (0<<5))
8 彙編編寫延時函數並實現LED閃爍效果
8.1閃爍效果原理分析
閃爍 = 亮 + 延時 + 滅 + 延時 + 亮 + 延時 ······
8.2 彙編編寫延時函數
彙編編寫延時函數的原理,用一個寄存器存放一個數字,然後在循環中每個循環裏給數字減1,然後再判斷這個數字的值是否爲0.如果爲0則停止循環,如果不爲0則繼續循環。
// 延時函數:函數名:delay
delay:
ldr r2, =9000000
ldr r3, =0x0//這兩句是初始化
delay_loop:
sub r2, r2, #1 //r2 = r2 - 1
cmp r2, r3 //cmp會影響Z標誌位,如果r2等於r3則Z=1,
//下一句中eq就會成立
bne delay_loop //這三句是函數體
mov pc, lr //函數調用返回
8.3 用匯編寫死循環也很簡單
flash:
亮-延時-滅-延時... //循環體
b flash
8.4 彙編編寫及調用函數的方式
彙編中整個彙編的主程序是一個死循環,這個死循環是我們彙編程序的主體,類似於C中的main函數。其他函數必須寫在這個主死循環程序的後面(死循環外),不然會出錯。
彙編編寫delay延時函數時,要注意函數的初始化和函數體的位置,不能把初始化寫在了循環體內。
彙編中調用函數用bl指令,子函數中最後用mov pc, lr來返回。
編程操控一個硬件的步驟:
1 分析硬件工作原理
2 分析原理圖
3 分析數據手冊
4 找到相關的SFR
5 寫代碼設置寄存器得到想要的效果
9.自己做的。板子上有4顆LED的(還有個在GPD0_1),四個燈依次點亮
1.分析硬件工作原理(底板x210bv3)
1.觀察第四個燈D25:PWMTOUT1
所以要查覈心板x210cv3,[PWMTOUT1接在了核心板x210cv3,利用好pdf閱讀器中的搜索功能],發現PWMTOUT1對應的就是GPD0_1
2.分析數據手冊
在S5PV210_UM_REV1.1中查找GPIO對應的SFR——GPJ0、GPD0
4.找到相關的SFR
然後相關的SFR爲GPJ0_CON、GPJ0_DAT、GPD0_CON、GPD0_DAT
5 寫代碼設置寄存器得到想要的效果 文件名<9.leds_s>和<11.leds_swang>
1.觀察第四個燈D25:PWMTOUT1
所以要查覈心板x210cv3,[PWMTOUT1接在了核心板x210cv3,利用好pdf閱讀器中的搜索功能],發現PWMTOUT1對應的就是GPD0_1
2.分析數據手冊
在S5PV210_UM_REV1.1中查找GPIO對應的SFR——GPJ0、GPD0
4.找到相關的SFR
然後相關的SFR爲GPJ0_CON、GPJ0_DAT、GPD0_CON、GPD0_DAT
5 寫代碼設置寄存器得到想要的效果 文件名<9.leds_s>和<11.leds_swang>
1.觀察第四個燈D25:PWMTOUT1
所以要查覈心板x210cv3,[PWMTOUT1接在了核心板x210cv3,利用好pdf閱讀器中的搜索功能],發現PWMTOUT1對應的就是GPD0_1
2.分析數據手冊
在S5PV210_UM_REV1.1中查找GPIO對應的SFR——GPJ0、GPD0
4.找到相關的SFR
然後相關的SFR爲GPJ0_CON、GPJ0_DAT、GPD0_CON、GPD0_DAT
5 寫代碼設置寄存器得到想要的效果 文件名<9.leds_s>和<11.leds_swang>
/*
*文件名: 9.leds_s
*作者:
*描述: 流水燈-四個燈依次點亮
*/
#define GPJ0CON 0xE0200240
#define GPJ0DAT 0xE0200244
#define GPD0CON 0xE02000A0
#define GPD0DAT 0xE02000A4
.global _start //用.global把_start鏈接屬性改爲外部,這樣其他文件就可以看見_start了
_start:
//第一步:把0x11111111寫入0xE0200240(GPJ0CON)位置。意思是把8個引腳全設置爲輸出模式,代碼不變。
ldr r0, =0x11111111 //從後面的=可以看出用的是ldr僞指令,因爲需要編譯器來判斷這個數
ldr r1, =GPJ0CON //是合法立即數還是非法立即數。一般寫代碼都用ldr僞指令
str r0, [r1] //寄存器間接尋址功能是把r0中的數寫入到r1中的數爲地址的內存中去
//第二步:把0x1111寫入0xE02100A0(GPD0CON)位置。
ldr r0, =10000 //ldr r0, =(1<<4)
ldr r1, =GPD0CON
str r0, [r1]
flash:
//第1步:第一顆燈亮
//ldr r0, = ((0<<3) | (1<<4) | (1<<5))
ldr r0,= GPD0DAT
ldr r1,= 1111 //ldr r1,= (1<<1)
str r1,[r0]
ldr r0, = ~(1<<3) //1000 位取反 爲 0111
ldr r1, =GPJ0DAT
str r0,[r1] //把0寫入到GPJ0DAT寄存器中,引腳即輸出低電平,LED點亮
//然後:延時
bl delay
//第2步:第二顆燈亮
ldr r0,= GPD0DAT
ldr r1,= 1111
str r1,[r0]
ldr r0, = ~(1<<4)
ldr r1, =GPJ0DAT
str r0,[r1] //把0寫入到GPJ0DAT寄存器中,引腳即輸出低電平,LED點亮
//然後:延時
bl delay
//第3步:第三顆燈亮
ldr r0,= GPD0DAT
ldr r1,= 1111
str r1,[r0]
ldr r0, = ~(1<<5)
ldr r1, =GPJ0DAT
str r0, [r1] //把0寫入到GPJ0DAT寄存器中,引腳即輸出低電平,LED點亮
//然後:延時
bl delay
//第4步:第四課燈亮
ldr r0, =1101 //ldr r0, =(0<<1)
ldr r1, =GPD0DAT
str r0, [r1]
ldr r0,= GPJ0DAT
ldr r1,= (1<<3)|(1<<4)|(1<<5)
str r1,[r0]
//然後:延時
bl delay
b flash
// 延時函數:函數名:delay
delay:
ldr r2, =9000000
ldr r3, =0x0
delay_loop:
sub r2, r2, #1 //r2 = r2 - 1
cmp r2, r3 //cmp會影響Z標誌位,如果r2等於r3則Z=1,下一句中eq就會成立
bne delay_loop
mov pc, lr //函數調用返回