Linux|流水灯&蜂鸣器

引语

记录学习路程,抛砖引玉。如有更好的算法或者出现错误,欢迎指点。

内容介绍

四个GPIO分别控制四个LED灯
D7 ----- GPIOE13
D8 ----- GPIOC17
D9 ----- GPIOC8
D10 ----- GPIOC7

还有一个是蜂鸣器 ----- GPIOC14

裸机程序

void delay(int data);
void _start(void)//_start函数必须是编写的第一个函数
{
	
	//1.将GPIOC8配置成IO功能,GPIOCALTFN0[17:16]=01b      这里的[17,16]是根据查手册获取
	*(unsigned int *)(0xC0010000+0xC020) &= ~(1<<17); 
	*(unsigned int *)(0xC0010000+0xC020) |= (1<<16);
	//2.将GPIOC8引脚的IO功能配置成OUTPUT,GPIOCOUTENB[8]=1b
	*(unsigned int *)(0xC0010000+0xC004) |= (1<<8);
	while(1)
	{
		//3.GPIOC8引脚输出低电平,LED9亮,GPIOCOUT[8]=0
		*(unsigned int *)(0xC0010000+0xC000) &= ~(1<<8);
		delay(0x2000000);
		//4.GPIOC8引脚输出高电平,LED9灭,GPIOCOUT[8]=0
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<8);
		delay(0x2000000);
	}
}

void delay(int data)
{
	while(data--);	
}

注意:_start()必须是第一个定义的函数。delay()放在后面。

IO引脚配置(GPIOC8—D9为例)

IO口信息通过查手册获取

1.将GPIOC8配置成IO功能。
----复用功能选择寄存器–GPIOxALTFN0:配置引脚0~15
–GPIOxALTFN1:配置引脚16~31
x=ABCDE
该寄存器是一个32bits的寄存器,每个位为一组。每一组控制一个引脚的功能。

例:配置GPIOC8的IO功能
GPIOCALTFN0[17:16] =

具体哪个alt function是IO功能,需要查找手册的第二章。知道IO功能是复用功能1.

所以:
GPIOCALTFN0[17:16] = 01b

2.将GPIOC8引脚的IO功能配置成OUTPUT
----GPIO输出使能寄存器–GPIOxOUTENB

GPIOCOUTENB[8]=1b

3.GPIOC8引脚输出低电平,LED9亮
----GPIO输出电平的寄存器–GPIOxOUT

GPIOCOUT[8]=0;

4.GPIOC8引脚输出高电平,LED9灭
----GPIO输出电平的寄存器–GPIOxOUT

GPIOCOUT[8]=1;

裸机调试

1、更新uboot(启动引导程序)–刷机
注意:刷机过程只需要做一次,主要是为了得到loady命令,开发板上默认烧写的uboot中是没有loady命令的。
(1)使用USB线连接开发板和PC机。
(2)启动开发板,进入UBoot的命令行,启动3秒倒计时前输入任意键,进入uboot命令行。
Card did not respond to voltage select!
Net: GEC6818 mac init…
dwmac.c0060000
Hit any key to stop autoboot: 0
GEC6818#
GEC6818#
GEC6818#
GEC6818#
(3)输入fastboot
GEC6818# fastboot
Fastboot Partitions:
mmc.2: GECuboot, img : 0x200, 0x78000
mmc.2: 2ndboot, img : 0x200, 0x4000
mmc.2: bootloader, img : 0x8000, 0x70000
mmc.2: boot, fs : 0x100000, 0x4000000
mmc.2: system, fs : 0x4100000, 0x2f200000
mmc.2: cache, fs : 0x33300000, 0x1ac00000
mmc.2: misc, fs : 0x4e000000, 0x800000
mmc.2: recovery, fs : 0x4e900000, 0x1600000
mmc.2: userdata, fs : 0x50000000, 0x0
Support fstype : 2nd boot factory raw fat ext4 emmc nand ubi ubifs
Reserved part : partmap mem env cmd
DONE: Logo bmp 311 by 300 (3bpp), len=280854
DRAW: 0x47000000 -> 0x46000000
Load USB Driver: android
Core usb device tie configuration done
OTG cable Connected!
(4)安装USB驱动----驱动精灵
安装驱动成功后,显示接口:Android ADB interface
(5)执行一个批处理文件
auto.bat
注意:需要用管理员权限执行批处理文件。完成了U-boot烧写,此时uboot中存在了loady命令,后面不需要再更新uboot了。

2.下载执行程序led.bin(使用uboot中的loady命令)
1)重启开发板,进入uboot命令行
Card did not respond to voltage select!
Net: GEC6818 mac init…
dwmac.c0060000
Hit any key to stop autoboot: 0
GEC6818#
GEC6818#
GEC6818#
GEC6818#
GEC6818#
2)下载led.bin裸机的执行程序
使用uboot的loady命令下载led.bin
GEC6818# loady 0x40000000 led.bin
C
3)使用Ymodem协议传输led.bin
开始 ymodem 传输。 按 Ctrl+C 取消。
100% 212 bytes 53 bytes/s 00:00:04 0 Errors
xyzModem - Cksum mode, 4(SOH)/0(STX)/0(CAN) packets, 13 retries
GEC6818#
此处需要注意,不同使用rx命令和Xmodem协议传输文件,因为uboot不支持rx命令,只支持loady命令,用ymodem协议下载。
4)执行下载后的led.bin
GEC6818# go 0x40000000
注意:0x40000000地址是开发板运行内存的地址,重启开发板后,需要重新下载led.bin文件。
5)观察开发板上LED8闪烁。

流水灯&蜂鸣器代码

以下是在虚拟机shell编译出bin文件的执行代码
我的电脑路径是gec@ubuntu:/mnt/hgfs/ub2$ 以下都是省略前面 $作为Linux开头标志

$ arm-none-linux-gnueabi-gcc -o led.c -c -nostdlib
$ arm-none-linux-gnueabi-ld -Ttext 0x40000000 -o led.elf led.o
$ arm-none-linux-gnueabi-objcopy -o binary led.elf led.bin
$ arm-none-linux-gnueabi-objdump -D led.elf > led.dis

这个是实现功能的C语言文件led.c代码

void delay(int data);
void _start(void)//_start函数必须是编写的第一个函数
{
	
	//1.将GPIOC8配置成IO功能,GPIOCALTFN0[17:16]=01b
	*(unsigned int *)(0xC0010000+0xC020) &= ~(1<<17); 
	*(unsigned int *)(0xC0010000+0xC020) |= (1<<16);

	*(unsigned int *)(0xC0010000+0xC020) &= ~(1<<15); 
	*(unsigned int *)(0xC0010000+0xC020) |= (1<<14);		
	
  //*(unsigned int *)(0xC0010000+0xE024) &= ~(1<<27);
	*(unsigned int *)(0xC0010000+0xE024) |= (1<<27); 
	*(unsigned int *)(0xC0010000+0xE024) |= (1<<26);
	
	*(unsigned int *)(0xC0010000+0xC024) &= ~(1<<3); 
	*(unsigned int *)(0xC0010000+0xC024) |= (1<<2);
	
	//蜂鸣器
	*(unsigned int *)(0xC0010000+0xC020) &= ~(1<<29); 
	*(unsigned int *)(0xC0010000+0xC020) |= (1<<28);
	
	
	
	
	//2.将GPIOC8引脚的IO功能配置成OUTPUT,GPIOCOUTENB[8]=1b
	*(unsigned int *)(0xC0010000+0xC004) |= (1<<7);
	
	*(unsigned int *)(0xC0010000+0xC004) |= (1<<8);
	
	*(unsigned int *)(0xC0010000+0xC004) |= (1<<17);
	
	*(unsigned int *)(0xC0010000+0xE004) |= (1<<13);
	
	//蜂鸣器
	*(unsigned int *)(0xC0010000+0xC004) |= (1<<14);
	
	

	
	while(1)
	{
		*(unsigned int *)(0xC0010000+0xC000) &= ~(1<<7);
		
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<8);
	    *(unsigned int *)(0xC0010000+0xE000) |= (1<<13);
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<17);
		delay(0x2000000);
		
		
		*(unsigned int *)(0xC0010000+0xC000) &= ~(1<<8);
		
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<7);
		*(unsigned int *)(0xC0010000+0xE000) |= (1<<13);
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<17);
		delay(0x2000000);
		
		
		*(unsigned int *)(0xC0010000+0xC000) &= ~(1<<17);
	
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<7);
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<8);
	    *(unsigned int *)(0xC0010000+0xE000) |= (1<<13);
		delay(0x2000000);
		
		
		*(unsigned int *)(0xC0010000+0xE000) &= ~(1<<13);
		
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<7);
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<8);
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<17);
		delay(0x2000000);
		
		//蜂鸣器
		*(unsigned int *)(0xC0010000+0xC000) |= (1<<14);
		delay(0x10000000);
		*(unsigned int *)(0xC0010000+0xC000) &= ~(1<<14);
		delay(0x2000000);
	}
	
}

void delay(int data)
{
	while(data--);	
}




  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ver 是一种硬件描述语言,可以用来描述数字电路的行为。流水灯、数码管和蜂鸣器都是数字电路中常见的模块,可以用 Verilog 来实现以下是一个基于 Verilog 的流水灯、数码管和蜂鸣器的设计: ```verilog // 定义模块 module led_display( input clk, // 时钟信号 output reg [3:0] leds, // 四个 LED 灯 output reg [6:0] segs, // 七段数码管 output reg beep // 蜂鸣器 ); // 定义计数器参数 parameter COUNTER_MAX = 24'd500000; // 最大计数值 // 定义状态机参数 parameter STATE_IDLE = 2'd0; // 空闲状态 parameter STATE_LED = 2'd1; // 流水灯状态 parameter STATE_COUNT = 2'd2; // 计数器状态 parameter STATE_DISPLAY = 2'd3; // 数码管显示状态 parameter STATE_BEEP = 2'd4; // 蜂鸣器状态 // 定义状态机变量 reg [1:0] state = STATE_IDLE; reg [23:0] counter = 0; // 计数器 // 定义流水灯变量 reg [3:0] led_pattern = 4'b0001; // LED 灯模式 // 定义计数器变量 reg [7:0] count_value = 8'h00; // 计数器初始值 // 定义数码管变量 reg [3:0] seg_pattern = 4'b0000; // 数码管模式 reg [1:0] seg_index = 2'd0; // 数码管索引 // 定义蜂鸣器变量 reg beep_pattern = 1'b0; // 蜂鸣器模式 // 空闲状态 always @ (posedge clk) begin if (state == STATE_IDLE) begin // 等待一段时间后进入流水灯状态 if (counter >= COUNTER_MAX) begin state <= STATE_LED; counter <= 0; end else begin counter <= counter + 1; end end end // 流水灯状态 always @ (posedge clk) begin if (state == STATE_LED) begin // 更新 LED 灯模式 led_pattern <= {led_pattern[2:0], led_pattern[3]}; // 进入计数器状态 state <= STATE_COUNT; end end // 计数器状态 always @ (posedge clk) begin if (state == STATE_COUNT) begin // 计数器加 1 count_value <= count_value + 1; // 计数器溢出后进入数码管显示状态 if (count_value == 8'hFF) begin state <= STATE_DISPLAY; counter <= 0; end end end // 数码管显示状态 always @ (posedge clk) begin if (state == STATE_DISPLAY) begin // 更新数码管模式和索引 case (seg_index) 2'd0: seg_pattern <= 4'b0111; 2'd1: seg_pattern <= 4'b1000; 2'd2: seg_pattern <= 4'b1001; 2'd3: seg_pattern <= 4'b0000; endcase seg_index <= seg_index + 1; if (seg_index == 2'd4) begin seg_index <= 0; end // 等待一段时间后进入蜂鸣器状态 if (counter >= COUNTER_MAX) begin state <= STATE_BEEP; counter <= 0; end else begin counter <= counter + 1; end end end // 蜂鸣器状态 always @ (posedge clk) begin if (state == STATE_BEEP) begin // 播放蜂鸣器声音 beep_pattern <= ~beep_pattern; // 回到空闲状态 state <= STATE_IDLE; end end // 输出模块 always @ (*) begin leds = led_pattern; segs = seg_pattern; beep = beep_pattern; end endmodule ``` 这个 Verilog 模块包含一个状态机,用于控制流水灯、计数器、数码管和蜂鸣器的行为。模块的输入包括时钟 clk,输出包括四个 LED 灯 leds、七段数码管 segs 和蜂鸣器 beep。 模块的状态机按照如下顺序运行: 1. 空闲状态:等待一段时间后进入流水灯状态。 2. 流水灯状态:更新 LED 灯模式,进入计数器状态。 3. 计数器状态:计数器加 1,计数器溢出后进入数码管显示状态。 4. 数码管显示状态:更新数码管模式和索引,等待一段时间后进入蜂鸣器状态。 5. 蜂鸣器状态:播放蜂鸣器声音,回到空闲状态。 这个 Verilog 模块可以通过 Vivado 等 FPGA 开发工具进行编译和下载到 FPGA 板上运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值