05_I.MX6ULL工程管理与蜂鸣器实验
目錄
BSP工程管理
有源蜂鳴器簡介
硬件原理分析
實驗源碼
bsp源碼
main.c匯編文件源碼
鏈接文件源碼
Makefile源碼
BSP工程管理
在實際工作中將所有源碼放到工程的根目錄下,如果工程文件比較少的話這樣做無可厚非,但是如果工程源文件達到幾十、甚至數百個的時候,這樣一股腦全部放到根目錄下就會使工程顯得混亂不堪。所以我們必須對工程文件做管理,將不同功能的源碼文件放到不同的目錄中。另外我們也需要將源碼文件中,所有完成同一個功能的代碼提取出來放到一個單獨的文件中,也就是對程序分功能管理。
第一步:先建立一個項目文件夾
?
第二步建立相應存放代碼的文件夾
01_imx6ul是一些關于芯片的源碼
02_bsp是用來專門存放啟動的文件夾
03_obj是用來存放編譯時候的一些文件
04_project是存放main.c和匯編文件
Imx6ul.lds是鏈接腳本
Imxdownload是一個燒錄sd卡的腳本
load.imx是燒錄腳本生成的,里面內容就是頭部加bin文件,最終燒到sd卡里的就是這個文件
Makedfile 自動編譯腳本
第三步在02_bsp文件夾下創建各個外設的文件夾實現了模塊化管理
有源蜂鳴器簡介
蜂鳴器常用于計算機、打印機、報警器、電子玩具等電子產品中,常用的蜂鳴器有兩種:有源蜂鳴器和無源蜂鳴器,這里的有“源”不是電源,而是震蕩源,有源蜂鳴器內部帶有震蕩源,所以有源蜂鳴器只要通電就會叫。無源蜂鳴器內部不帶震蕩源,直接用直流電是驅動不起來的,需要 2K-5K 的方波去驅動。這里使用的是有源蜂鳴器,因此只要給其供電就會工作。
有源蜂鳴器只要通電就會叫,可以由一個IO來控制其通斷,一般使用三極管來搭建這個電路。
?
硬件原理分析
通過一個PNP型的三極管8550來驅動蜂鳴器,通過SNVS_TAMPER1這個IO來控制三極管 Q1的導通,當SNVS_TAMPER1輸出低電平的時候Q1導通,相當于蜂鳴器的正極連接到DCDC_3V3,蜂鳴器形成一個通路,因此蜂鳴器會鳴叫。同理,當SNVS_TAMPER1輸出高電平的時候Q1不導通,那么蜂鳴器就沒有形成一個通路,因此蜂鳴器也就不會鳴叫。
實驗源碼
bsp源碼
#ifndef __BSP_CLK_H #define __BSP_CLK_H#include "imx6ul.h"/* 函數聲明 */ void clk_enable(void);#endif #include "bsp_clk.h" #include "imx6ul.h" /** @description : 使能I.MX6U所有外設時鐘* @param : 無* @return : 無*/ void clk_enable(void) {CCM->CCGR0 = 0XFFFFFFFF;CCM->CCGR1 = 0XFFFFFFFF;CCM->CCGR2 = 0XFFFFFFFF;CCM->CCGR3 = 0XFFFFFFFF;CCM->CCGR4 = 0XFFFFFFFF;CCM->CCGR5 = 0XFFFFFFFF;CCM->CCGR6 = 0XFFFFFFFF; } #ifndef __BSP_DELAY_H #define __BSP_DELAY_H #include "imx6ul.h"/* 函數聲明 */ void delay(volatile unsigned int n);#endif #include "bsp_delay.h" #include "imx6ul.h" /** @description : 短時間延時函數* @param - n : 要延時循環次數(空操作循環次數,模式延時)* @return : 無*/ void delay_short(volatile unsigned int n) {while(n--){} }/** @description : 延時函數,在396Mhz的主頻下* 延時時間大約為1ms* @param - n : 要延時的ms數* @return : 無*/ void delay(volatile unsigned int n) {while(n--){delay_short(0x7ff);} } #ifndef __BSP_LED_H #define __BSP_LED_H #include "imx6ul.h"#define LED0 0/* 函數聲明 */ void led_init(void); void led_switch(int led, int status); #endif #include "bsp_led.h" #include "imx6ul.h"/** @description : 初始化LED對應的GPIO* @param : 無* @return : 無*/ void led_init(void) {/* 1、初始化IO復用 */IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0); /* 復用為GPIO1_IO03 *//* 2、、配置GPIO1_IO03的IO屬性 *bit 16:0 HYS關閉*bit [15:14]: 00 默認下拉*bit [13]: 0 kepper功能*bit [12]: 1 pull/keeper使能*bit [11]: 0 關閉開路輸出*bit [7:6]: 10 速度100Mhz*bit [5:3]: 110 R0/6驅動能力*bit [0]: 0 低轉換率*/IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0);/* 3、初始化GPIO,GPIO1_IO03設置為輸出*/GPIO1->GDIR |= (1 << 3); /* 4、設置GPIO1_IO03輸出低電平,打開LED0*/GPIO1->DR &= ~(1 << 3); }/** @description : LED控制函數,控制LED打開還是關閉* @param - led : 要控制的LED燈編號* @param - status : 0,關閉LED0,1 打開LED0* @return : 無*/ void led_switch(int led, int status) { switch(led){case LED0:if(status == ON)GPIO1->DR &= ~(1<<3); /* 打開LED0 */else if(status == OFF)GPIO1->DR |= (1<<3); /* 關閉LED0 */break;} } #ifndef __BSP_BEEP_H #define __BSP_BEEP_H#include "imx6ul.h"/* 函數聲明 */ void beep_init(void); void beep_switch(int status); #endif #include "bsp_beep.h" #include "imx6ul.h" /** @description : 初始化蜂鳴器對應的IO* @param : 無* @return : 無*/ void beep_init(void) {/* 1、初始化IO復用,復用為GPIO5_IO01 */IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0); /* 2、、配置GPIO1_IO03的IO屬性 *bit 16:0 HYS關閉*bit [15:14]: 00 默認下拉*bit [13]: 0 kepper功能*bit [12]: 1 pull/keeper使能*bit [11]: 0 關閉開路輸出*bit [7:6]: 10 速度100Mhz*bit [5:3]: 110 R0/6驅動能力*bit [0]: 0 低轉換率*/IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0X10B0);/* 3、初始化GPIO,GPIO5_IO01設置為輸出 */GPIO5->GDIR |= (1 << 1); /* 4、設置GPIO5_IO01輸出高電平,關閉蜂鳴器 */GPIO5->DR |= (1 << 1); }/** @description : 蜂鳴器控制函數,控制蜂鳴器打開還是關閉* @param - status : 0,關閉蜂鳴器,1 打開蜂鳴器* @return : 無*/ void beep_switch(int status) { if(status == ON)GPIO5->DR &= ~(1 << 1); /* 打開蜂鳴器 */else if(status == OFF)GPIO5->DR |= (1 << 1); /* 關閉蜂鳴器 */ }main.c匯編文件源碼
.global _start /* 全局標號 *//** 描述: _start函數,程序從此函數開始執行,此函數主要功能是設置C* 運行環境。*/_start:/* 進入SVC模式 */mrs r0, cpsrbic r0, r0, #0x1f /* 將r0寄存器中的低5位清零,也就是cpsr的M0~M4 */orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */msr cpsr, r0 /* 將r0 的數據寫入到cpsr_c中 *//* 設置棧指針,* 注意:IMX6UL的堆棧是向下增長的!* 堆棧指針地址一定要是4字節地址對齊的!!!* DDR范圍:0X80000000~0X9FFFFFFF*/ldr sp,=0X80200000 /* 設置用戶模式下的棧首地址為0X80200000,大小為2MB */b main /* 跳轉到main函數 */ #include "bsp_clk.h"#include "bsp_delay.h"#include "bsp_led.h"#include "bsp_beep.h"#include "imx6ul.h"/** @description : main函數* @param : 無* @return : 無*/int main(void){clk_enable(); /* 使能所有的時鐘 */led_init(); /* 初始化led */beep_init(); /* 初始化beep */while(1) { /* 打開LED0和蜂鳴器 */led_switch(LED0,ON); beep_switch(ON);delay(1000);/* 關閉LED0和蜂鳴器 */led_switch(LED0,OFF); beep_switch(OFF);delay(1000);}return 0;}鏈接文件源碼
SECTIONS{. = 0X87800000;.text :{03_obj/start.o *(.text)}.rodata ALIGN(4) : {*(.rodata*)} .data ALIGN(4) : { *(.data) } __bss_start = .; .bss ALIGN(4) : { *(.bss) *(COMMON) } __bss_end = .;}第1行先寫了一個關鍵字“SECTIONS”,后面跟了一個大括號,這個大括號和最后一行的大括號是一對,這是必須的。看起來就跟C語言里面的函數一樣。
第2行對一個特殊符號“.”進行賦值“.”在鏈接腳本里面叫做定位計數器,默認的定位計數器為0。設置定位計數器為0X87800000,因為我們的鏈接地址就是0X87800000開始。就是用戶編寫的代碼地址也就是這里的匯編文件。
第3行的“.text”是段名,后面的冒號是語法要求,冒號后面的大括號里面可以填上要鏈接到“.text”這個段里面的所有文件, "*(.text)"中的“*”是通配符,表示所有輸入文件的.text段都放到".text”中,設置鏈接到開始位置的文件為start.o,因為start.o里面包含著第一個要執行的指令,所以一定要鏈接到最開始的地方。
第4行,只讀數據放在緊接代碼段(tex段)后面de地方,ALIGN(4)4字節對齊。
第5行放可讀可寫數據。
第6行記錄__bss段存儲開始地址_bss段就是存儲了一些定義了但是沒有被使用的變量。
第7行__bss存放緊跟在可讀可寫數據后面。
第8行記錄__bss段結束地址。
Makefile源碼
CROSS_COMPILE ?= arm-linux-gnueabihf-TARGET ?= beepCC := $(CROSS_COMPILE)gccLD := $(CROSS_COMPILE)ldOBJCOPY := $(CROSS_COMPILE)objcopyOBJDUMP := $(CROSS_COMPILE)objdumpINCDIRS := 01_imx6ul \02_bsp/01_clk \02_bsp/03_led \02_bsp/02_delay \02_bsp/04_beepSRCDIRS := 04_project \02_bsp/01_clk \02_bsp/03_led \02_bsp/02_delay \02_bsp/04_beepINCLUDE := $(patsubst %, -I %, $(INCDIRS))SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))SFILENDIR := $(notdir $(SFILES))CFILENDIR := $(notdir $(CFILES))SOBJS := $(patsubst %, 03_obj/%, $(SFILENDIR:.S=.o))COBJS := $(patsubst %, 03_obj/%, $(CFILENDIR:.c=.o))OBJS := $(SOBJS) $(COBJS)VPATH := $(SRCDIRS).PHONY: clean$(TARGET).bin : $(OBJS)$(LD) -Timx6ul.lds -o $(TARGET).elf $^$(OBJCOPY) -O binary -S $(TARGET).elf $@$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis$(SOBJS) : 03_obj/%.o : %.S$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<$(COBJS) : 03_obj/%.o : %.c$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<clear:rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)1~6行都是給變量賦值
7行是給變量賦值所有包含的.h文件路徑
8行是給變量賦值所有包含源文件.c.s文件路徑
9行給頭文件前面加一個-I 并賦值給變量
10行是給查找路徑下的所有.s和.c文件賦值給變量(帶路徑)
11~12行是去掉路徑只留下文件名
13~14行生成.o文件的路徑
15行所有.o文件路徑的集合
16行TARGET.bin依賴于OBJS變量的.o文件
17行鏈接腳本
18行生成二進制文件
19行生成反匯編文件
20行SOBJS變量依賴03_obj/%.o文件下的.o文件,文件下面的.o文件又依賴于.s文件
21行編譯生成.o文件
22~23行和上面2行同理只不過是依賴.c
24行刪除編譯過程中的文件
總結
以上是生活随笔為你收集整理的05_I.MX6ULL工程管理与蜂鸣器实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超详细!ArrayList源码图文解析
- 下一篇: [bzoj4566][HAOI2016]