文章目录
简单编写实现一个裸板环境下使用的“shell”功能程序,可以控制LED、beep等。
main主程序设计
主要函数:strcmp实现
LED初始化及控制功能实现
UART初始化及控制功能实现
使用Makefile编译
执行结果
简单编写实现一个裸板环境下使用的“shell”功能程序,可以控制LED、beep等。
main主程序设计 #include "uart.h" #include "strcmp.h" #include "led.h" //保存从上位机接收的数据信息 static char buf[32]; void main(void) { //1.初始化UART uart_init(); //2.初始化LED led_init(); //3.根据用户需求完成业务 while(1) { uart_puts("\n Shell#"); uart_gets(buf, 32); if(!my_strcmp(buf, "led on")) led_on(); else if(!my_strcmp(buf, "led off")) led_off(); else uart_puts("\n Your command is invalid\n"); } }
主要函数:strcmp实现
实现strcmp字符串比较函数,用于对比用户命令的输入。
- strcmp.h
#ifndef __STRCMP_H #define __STRCMP_H /*功能:比较字符串函数声明 *返回值: str1=str2:返回0 str1>str2:返回大于0 str1<str2:返回小于0 参数: str1:要比较的字符串 str2:要比较的字符串 * */ extern int my_strcmp(const char *str1, const char *str2); #endif
- strcmp.c
#include “strcmp.h” /*str1 = "hello", str2 = "hfllo"*/ int my_strcmp(const char *str1, const char *str2) { while(*str1) { if(*str1 != *str2) return *str1 - *str2; str1++; str2++; } return *str1 - *str2; }
LED初始化及控制功能实现
- led.h
#ifndef __LED_H #define __LED_H /*声明寄存器的基地址信息*/ #define GPIOCOUT (*(volatile unsigned long *)0xC001C000) #define GPIOCOUTENB (*(volatile unsigned long *)0xC001C004) #define GPIOCALTFN0 (*(volatile unsigned long *)0xC001C020) /*声明操作函数*/ extern void led_init(void); extern void led_on(void); extern void led_off(void); #endif
- led.c
#include "led.h" //初始化函数定义 void led_init(void) { //1.配置引脚功能为GPIO功能 GPIOCALTFN0 &= ~(3 << 24); GPIOCALTFN0 |= (1 << 24); //2.配置引脚为输出功能 GPIOCOUTENB |= (1 << 12); } //开灯函数定义 void led_on(void) { //1.配置输出寄存器为0 GPIOCOUT &= ~(1 << 12); } //关灯函数定义 void led_off(void) { //1.配置输出寄存器为1 GPIOCOUT |= (1 << 12); }
UART初始化及控制功能实现
- uart.h
#ifndef __UART_H #define __UART_H /*UART相关寄存器定义*/ #define ULCON0 (*(volatile unsigned long *)0xC00A1000) #define UCON0 (*(volatile unsigned long *)0xC00A1004) #define UTRSTAT0 (*(volatile unsigned long *)0xC00A1010) #define UTXH0 (*(volatile unsigned long *)0xC00A1020) #define URXH0 (*(volatile unsigned long *)0xC00A1024) #define UBRDIV0 (*(volatile unsigned long *)0xC00A1028) #define UFRACVAL0 (*(volatile unsigned long *)0xC00A102C) #define GPIODALTFN0 (*(volatile unsigned long *)0xC001D020) #define GPIODALTFN1 (*(volatile unsigned long *)0xC001D024) #define UARTCLKENB (*(volatile unsigned long *)0xC00A9000) #define UARTCLKGENOL (*(volatile unsigned long *)0xC00A9004) /*UART操作函数声明*/ //初始化函数 extern void uart_init(void); //发送字符函数 extern void uart_putc(char c); //发送字符串函数 extern void uart_puts(char *str); //接收字符函数 extern char uart_getc(void); //接收字符串函数 extern void uart_gets(char buf[], int len); #endif
- uart.c
#include "uart.h" //初始化函数的定义 void uart_init(void) { //1.配置RX和TX对应的引脚功能分别为UARTRXD0和UARTTXD0功能 //GPIOD14配置UARTRXD0 //GPIODALTFN0[29:28]=01 GPIODALTFN0 &= ~(3 << 28); GPIODALTFN0 |= (1 << 28); //GPIOD18配置UARTTXD0 //GPIODALTFN1[5:4]=01 GPIODALTFN1 &= ~(3 << 4); GPIODALTFN1 |= (1 << 4); //2.配置UART的时钟为50MHZ //此时钟给波特率产生器使用 //PLL[0]=800MHZ //n=800MHZ/50MHZ=16 //n=CLKDIV0+1=>CLKDIV0=15 //CLKDIV0=UARTCLKGENOL[12:5] UARTCLKGENOL &= ~(0xFF << 5); UARTCLKGENOL |= (0xF << 5); //3.配置UART的波特率为115200 //数据位为8 //不采用奇偶校验 //停止为为1位 ULCON0 = 3; UCON0 = 5; UBRDIV0 = 26; UFRACVAL0=2; //4.打开UART的时钟 UARTCLKENB |= (1 << 2); } //发送字符函数定义 //以软件形式将数据放到发送缓冲区 //发送移位器自动将数据一位一位的 //发送到TX数据线,速度就是115200 void uart_putc(char c) { //1.由于CPU把数据放到缓存区的速度要远远快于发送移位器把数据放到TX数据线上的速度,CPU再发送下一个字符的时候应该判断一下发送缓冲区是否为空,如果为空,可以发,否则继续死等待 while(!(UTRSTAT0 & 0x2)); //2.将数据放到发送缓冲区 UTXH0 = c; //3.发送回车字符 if(c == '\n') uart_putc('\r'); } //发送字符串函数定义 //str = "helloworld\n" void uart_puts(char *str) { while(*str) { uart_putc(*str); str++; } } //获取字符函数定义 char uart_getc(void) { //1.由于CPU读取UART接收缓冲区数据的速度 //要远远快于接收移位器从RX数据线获取数据的数据,所以CPU在读取数据的时候,首先要判断 //接收移位器的速度由波特率产生器决定 //接收缓冲区是否为空 //如果为空:CPU在原地死等 //如果不为空:CPU就可以读取数据 while(!(UTRSTAT0 & 0x1)); //2.从接收缓冲区寄存器读取数据 return (URXH0 & 0xFF); } //获取字符串函数定义 //调用:char buf[32];uart_gets(buf, 32) void uart_gets(char buf[], int len) { int i; for (i = 0; i < len - 1; i++) { //保存上位机发送的字符 buf[i] = uart_getc(); //上位机回显 uart_putc(buf[i]); //判断输入期间是否有回车操作 //如果有,跳出循环 if(buf[i] == '\r') break; } buf[i] = 0; //最后添加结束符 }
使用Makefile编译
- Makefile
#定义变量 NAME=shell BIN=$(NAME).bin ELF=$(NAME).elf OBJ=main.o uart.o led.o strcmp.o CROSS_COMPILE=arm-cortex_a9-linux-gnueabi- CC=$(CROSS_COMPILE)gcc LD=$(CROSS_COMPILE)ld OBJCOPY=$(CROSS_COMPILE)objcopy CP=cp RM=rm INSTALLPATH=/tftpboot #链接选项 LDFLAGS=-nostdlib -nostartfiles -Ttext=0x48000000 -emain #编译选项 CFLAGS=-nostdlib #定义编译规则 shell.bin:shell.elf arm-cortex_a9-linux-gnueabi-objcopy -O binary shell.elf shell.bin $(BIN):$(ELF) $(OBJCOPY) -O binary $(ELF) $(BIN) $(CP) $(BIN) $(INSTALLPATH) # # #shell.elf:main.o uart.o led.o strcmp.o # arm...ld -nostartfiles -nostdlib -... -o shell.elf main.o ... $(ELF):$(OBJ) $(LD) $(LDFLAGS) -o $(ELF) $(OBJ) #各种.o:各种.c # 各种编译 %.o:%.c $(CC) $(CFLAGS) -c -o $@ $< # # #伪目标 #当执行make clean时,仅仅执行clean伪目标对应的命令 clean: $(RM) $(BIN) $(ELF) $(OBJ)
执行结果
在板子上uboot界面执行:
tftp 48000000 shell.bin go 48000000