摘要:你點亮過多少板子的LED燈呢?有很多小伙伴要求講一下STM32、FPGA、Liunx他們之間有什么不同。不同點很多,口說無憑,今天就來點亮一下STM32、FPGA和Liunx板子的LED燈,大家大致看一下點燈流程和點燈環(huán)境以及點燈流程,就能大概的了解一下三者的區(qū)別,可以有選擇的去學(xué)習(xí)!
一、使用STM32點亮LED燈
STM32從字面上來理解ST是意法半導(dǎo)體,M是Microelectronics的縮寫,32 表示32位,合起來理解,STM32就是指ST公司開發(fā)的32位微控制器。在如今的32 位控制器當(dāng)中,STM32可以說是最璀璨的新星,它受寵若嬌,大受工程師和市場的青睞,無芯能出其右。首先使用STM32電亮一個led燈,大家現(xiàn)在回過頭來看是不是非常的簡單。
STM32初始化流程:
1、使能指定GPIO的時鐘。
2、初始化GPIO,比如輸出功能、上拉、速度等等。
3、STM32有的IO可以作為其它外設(shè)引腳,也就是IO復(fù)用,如果要將IO作為其它外設(shè)引腳使用的話就需要設(shè)置 IO 的復(fù)用功能。
4、最后設(shè)置GPIO輸出高電平或者低電平。
1、新建工程
2、代碼編寫
//LEDIO初始化
voidLED_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//使能GPIOF時鐘
//GPIOF9,F10初始化設(shè)置
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;//LED0和LED1對應(yīng)IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//普通輸出模式
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF,&GPIO_InitStructure);//初始化GPIO
GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);//GPIOF9,F10設(shè)置高,燈滅
}
3、編譯代碼
4、配置下載器
燒錄代碼
二、使用FPGA點亮LED燈
FPGA(Field Programmable Gate Array,簡稱 FPGA),譯文:現(xiàn)場可編程門陣列,一種主要以數(shù)字電路為主的集成芯片,于1985年由Xilinx創(chuàng)始人之一 Ross Freeman發(fā)明,屬于可編程邏輯器件PLD(Programmable Logic Device)的一種。真正意義上的第一顆FPGA芯片XC2064為Xilinx所發(fā)明,這個時間差不多比著名的摩爾定律晚20年左右,但是FPGA一經(jīng)發(fā)明,后續(xù)的發(fā)展速度之快,超出大多數(shù)人的想象。
計數(shù)器是在FPGA設(shè)計中最常用的一種時序邏輯電路,根據(jù)計數(shù)器的計數(shù)值我們可以精確的計算出FPGA內(nèi)部各種信號之間的時間關(guān)系,每個信號何時拉高、何時拉低、拉高多久、拉低多久都可以由計數(shù)器實現(xiàn)精確的控制。而讓計數(shù)器計數(shù)的是由外部晶振產(chǎn)生的時鐘,所以可以比較精準(zhǔn)的控制具體需要計數(shù)的時間。計數(shù)器一般都是從0開始計數(shù),計數(shù)到我們需要的值或者計數(shù)滿溢出后清零,并可以進(jìn)行不斷的循環(huán)。
本例我們讓計數(shù)器計數(shù)1s時間間隔,來實現(xiàn)led燈每隔1s閃爍一次的效果。
|
|
1、模塊框圖
|
|
2、RTL代碼的編寫
開始RTL代碼的編寫,RTL代碼編寫出的模塊叫RTL模塊(后文中也稱功能模塊、可綜合模塊)。之所以叫RTL代碼是因為用Verilog HDL在Resistances Transistors Logic(寄存器傳輸級邏輯)來描述硬件電路,RTL代碼能夠綜合出真實的電路以實現(xiàn)我們設(shè)計的功能,區(qū)別于不可綜合的仿真代碼。
`timescale1ns/1ns
//帶標(biāo)志信號的計數(shù)器
modulecounter
#(
parameterCNT_MAX=25'd24_999_999
)
(
inputwiresys_clk,//系統(tǒng)時鐘50Mhz
inputwiresys_rst_n,//全局復(fù)位
outputregled_out//輸出控制led燈
);
reg[24:0]cnt;//經(jīng)計算得需要25位寬的寄存器才夠500ms
regcnt_flag;
//cnt:計數(shù)器計數(shù),當(dāng)計數(shù)到CNT_MAX的值時清零
always@(posedgesys_clkornegedgesys_rst_n)
if(sys_rst_n==1'b0)
cnt<=?25'b0;
elseif(cnt1'b1;
else
cnt<=?25'b0;
//cnt_flag:計數(shù)到最大值產(chǎn)生的標(biāo)志信號
always@(posedgesys_clkornegedgesys_rst_n)
if(sys_rst_n==1'b0)
cnt_flag<=?1'b0;
elseif(cnt==CNT_MAX-1'b1)
cnt_flag<=?1'b1;
else
cnt_flag<=?1'b0;
//led_out:輸出控制一個LED燈,每當(dāng)計數(shù)滿標(biāo)志信號有效時取反
always@(posedgesys_clkornegedgesys_rst_n)
if(sys_rst_n==1'b0)
led_out<=?1'b0;
elseif(cnt_flag==1'b1)
led_out<=?~led_out;
endmodule
3、代碼的分析和綜合
4、 查看RTL視圖
5、Testbench代碼的編寫
`timescale1ns/1ns
moduletb_counter();
//wiredefine
wireled_out;
//regdefine
regsys_clk;
regsys_rst_n;
//初始化系統(tǒng)時鐘、全局復(fù)位
initialbegin
sys_clk=1'b1;
sys_rst_n<=?1'b0;
#20
sys_rst_n<=?1'b1;
end
//sys_clk:模擬系統(tǒng)時鐘,每10ns電平翻轉(zhuǎn)一次,周期為20ns,頻率為50Mhz
always#10sys_clk=~sys_clk;
initialbegin
$timeformat(-9,0,"ns",6);
$monitor("@time%t:led_out=%b",$time,led_out);
end
//-------------counter_inst--------------
counter
#(
.CNT_MAX(25'd24)
)
counter_inst
(
.sys_clk(sys_clk),//inputsys_clk
.sys_rst_n(sys_rst_n),//inputsys_rst_n
.led_out(led_out)//outputled_out
);
endmodule
6、ModelSim仿真波形
7、上板驗證
程序下載完畢后,會看到板卡LED0不斷閃爍,時間間隔為1秒。
三、使用I.MX6ULL IO點亮LED
嵌入式linux學(xué)習(xí)者大體可以分為兩類,一類是進(jìn)階用戶,主要指已經(jīng)有大量mcu工作經(jīng)驗的開發(fā)者, 他們希望進(jìn)階到更有難度,薪資更高的mpu開發(fā)中去。另一類則是學(xué)生用戶,主要是剛開始接觸嵌入式開發(fā)的大學(xué)生群體。
I.MX應(yīng)用處理器包括I.MX8、I.MX7、I.MX6及I.MX28系列,被廣泛應(yīng)用于工業(yè)控制、汽車電子領(lǐng)域,久經(jīng)市場考驗。而且它的產(chǎn)品線非常豐富,用戶熟悉其中一款產(chǎn)品后就能非常方便地遷移至不同的平臺。
一般拿到一款全新的芯片,第一個要做的事情的就是驅(qū)動其GPIO,控制其GPIO輸出高低電平,我們學(xué)習(xí)I.MX6U也一樣的,先來學(xué)習(xí)一下I.MX6U的GPIO。在學(xué)習(xí)I.MX6U的GPIO之前,我們可以對比一下STM32的GPIO初始化(如果沒有學(xué)過 STM32 就不用回顧了),我們以最常見的STM32F103為例來看一下STM32的GPIO初始化,示例代碼如下:
voidLED_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能PB端口時鐘
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//PB5端口配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度
GPIO_Init(GPIOB,&GPIO_InitStructure);//根據(jù)設(shè)定參數(shù)初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5);//PB.5輸出高
}
STM32初始化流程:
1、使能指定GPIO的時鐘。
2、初始化 GPIO,比如輸出功能、上拉、速度等等。
3、STM32 有的 IO 可以作為其它外設(shè)引腳,也就是 IO 復(fù)用,如果要將 IO 作為其它外設(shè)引腳使用的話就需要設(shè)置 IO 的復(fù)用功能。
4、最后設(shè)置GPIO輸出高電平或者低電平。
I.MX6U的GPIO一共有5組:GPIO1、GPIO2、GPIO3、GPIO4和GPIO5
,其中GPIO1有32個IO,GPIO2有22個IO,GPIO3有29個IO、GPIO4有29個IO,GPIO5最少,只有12個IO,這樣一共有124個GPIO
。
I.MX6ULL IO初始化流程:
1、使能時鐘,CCGR0—CCGR6
這7個寄存器控制著6ULL所有外設(shè)時鐘的使能。為了簡單,設(shè)置CCGR0~CCGR6這7
個寄存器全部為0XFFFFFFFF
,相當(dāng)于使能所有外設(shè)時鐘。
2、IO復(fù)用,將寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
的bit3~0
設(shè)置為0101=5
,這樣GPIO1_IO03
就復(fù)用為GPIO
。
3、寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
是設(shè)置GPIO1_IO03
的電氣屬性。包括壓擺率、速度、驅(qū)動能力、開漏、上下拉等。
4、配置GPIO功
能,設(shè)置輸入輸出。設(shè)置GPIO1_DR
寄存器bit3為1,也就是設(shè)置為輸出模式。設(shè)置GPIO1_DR
寄存器的bit3
,為1表示輸出高電平,為0表示輸出低電平。
匯編由一條一條指令構(gòu)成,指令就涉及到匯編指令。
Inta,b;
a=b;
假設(shè)a地址為0X20,b地址為0x30。
LDRR0,=0X30
LDRR1,[R0]
LDRR0,=0X20
STRR1,[R0]
我們在使用匯編編寫驅(qū)動的時候最常用的就是LDR
和STR
這兩個指令。
1、新建工程
新建工程文件夾:
新建裸機(jī)驅(qū)動文件夾新建LED燈文件夾2、在VSCode中編寫代碼
ubuntu中我們使用的是VScode編輯器來寫代碼,跟在windows中新建項目一樣,新建項目、保存工作區(qū),然后編寫代碼。
3、編寫代碼
.global_start/*全局標(biāo)號*/
_start:
/*1、使能所有時鐘ldf如果用大寫就全部用大寫,如果小寫就全部用小寫*/
ldrr0,=0X020C4068//將寄存器CCGR0地址0X020C4068存放到寄存器R0中
ldrr1,=0XFFFFFFFF//把寄存器x地址0Xffffffff存放到寄存器r1中
strr1,[r0]//把寄存器r1中的值(0XFFFFFFFF)寫入到寄存器r0里面的值作為地址的內(nèi)存里面
ldrr0,=0X020C406C/*將寄存器CCGR1地址(0X020C4068)存放到寄存器R0中*/
strr1,[r0]
ldrr0,=0X020C4070/*CCGR2*/
strr1,[r0]
ldrr0,=0X020C4074/*CCGR3*/
strr1,[r0]
ldrr0,=0X020C4078/*CCGR4*/
strr1,[r0]
ldrr0,=0X020C407C/*CCGR5*/
strr1,[r0]
ldrr0,=0X020C4080/*CCGR6*/
strr1,[r0]
/*2、設(shè)置GPIO1_IO03復(fù)用為GPIO1_IO03*/
ldrr0,=0X020E0068/*將寄存器SW_MUX_GPIO1_IO03_BASE加載到r0中*/
ldrr1,=0X5/*設(shè)置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE為5*/
strr1,[r0]
/*3、配置GPIO1_IO03的IO屬性
*bit16:0HYS關(guān)閉
*bit[15:14]:00默認(rèn)下拉
*bit[13]:0kepper功能
*bit[12]:1pull/keeper使能
*bit[11]:0關(guān)閉開路輸出
*bit[7:6]:10速度100Mhz
*bit[5:3]:110R0/6驅(qū)動能力
*bit[0]:0低轉(zhuǎn)換率
*/
ldrr0,=0X020E02F4/*寄存器SW_PAD_GPIO1_IO03_BASE*/
ldrr1,=0X10B0
strr1,[r0]
/*4、設(shè)置GPIO1_IO03為輸出*/
ldrr0,=0X0209C004/*寄存器GPIO1_GDIR*/
ldrr1,=0X0000008
strr1,[r0]
/*5、打開LED0
*設(shè)置GPIO1_IO03輸出低電平
*/
ldrr0,=0X0209C000/*寄存器GPIO1_DR*/
ldrr1,=0
strr1,[r0]
/*
*描述:loop死循環(huán)
*/
loop:
bloop
.global_start@全局標(biāo)號
/**/
4、編譯代碼
使用如下三條命令來編譯代碼:
arm-linux-gnueabihf-gcc-g-cleds.s-oled.o
arm-linux-gnueabihf-ld-Ttext0X87800000led.o-oled.elf
arm-linux-gnueabihf-objcopy-Obinary-S-gled.elfled.bin
編譯、鏈接、格式轉(zhuǎn)換
最終生成了led.o
led.elf
led.bin
三個文件。
5、燒寫代碼
STM32中代碼燒寫到內(nèi)部FLASH。IMX6ULL支持SD卡、EMMC、NAND、nor、SPI flash等啟動。裸機(jī)例程選擇燒寫到SD卡里面。在ubuntu下向SD卡燒寫裸機(jī)bin文件。燒寫不是將bin文件拷貝到SD卡中,而是將bin文件燒寫到SD卡絕對地址上。而且對于I.MX而言,不能直接燒寫bin文件,比如先在bin文件前面添加頭部。完成這個工作,需要使用正點原子提供的imxdownload軟件。
利用FileZilla Client軟件將imxdownload軟件發(fā)送到工程目錄下燒寫的三個命令:
ls/dev/sd*-l
chmod777imxdownload
./imxdownloadled.bin/dev/sdb
Imxdownload使用方法,確定要燒寫的SD卡文件,需要使用ls /dev/sd* -l
命令來檢測SD是哪一個文件,我的是/dev/sdb
。
給予imxdownload可執(zhí)行權(quán)限:Chmod 777 imxdownload
燒寫:./imxdownload led.bin /dev/sdb
Imxdownlaod
會向led.bin
添加一個頭部,生成新的load.imx
文件,這個load.imx
文件就是最終燒寫到SD卡里面去的。
這里要注意的是如果燒寫的速度在幾十MB/S左右的話,那么可能意味著燒寫失敗了。而且是因為SD卡沒找到而導(dǎo)致燒寫失敗,這個問題只能重啟 ubuntu解決。
之后就可以從讀卡器中把SD拔下來,然后插入到開發(fā)板中,將撥碼開關(guān)拔止SD卡模式,供電之后,藍(lán)色LED亮,紅色LED滅,兩秒鐘之后紅色LED亮。
最后,你覺得哪個板子點燈最簡單呢?
文章出處:【微信公眾號:嵌入式ARM】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
審核編輯:湯梓紅
-
FPGA
+關(guān)注
關(guān)注
1629文章
21736瀏覽量
603385 -
led
+關(guān)注
關(guān)注
242文章
23277瀏覽量
660873 -
STM32
+關(guān)注
關(guān)注
2270文章
10900瀏覽量
356010
原文標(biāo)題:史上最全的LED點燈程序,你都掌握了嗎?
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論