ULCON0 设置数据格式 UCON0 设置接收发送模式(轮询)暂停信号,回环,时钟源 UFCON0 UMCON0 UBRDIV0 设置波特率1 UDIVSLOT0 设置波特率2 UTRSTAT0 状态寄存器 bit[1] bit[0] UTXH0 发送缓冲寄存器 URXH0 接民缓冲寄存器
串口 TPAD PC 发送 接收(显示在屏幕上)
接收 发送(键盘)
#ifndef __UART_H__ #define __UART_H__ #define GPA0CON (*((volatile unsinged int*) 0xE0200000)) #define GPA0PUD (*((volatile unsinged int*) 0xE0200008)) #define ULCON0 (*((volatile unsinged int*) 0xE2900000)) #define UCON0 (*((volatile unsinged int*) 0xE2900004)) #define UFCON0 (*((volatile unsinged int*) 0xE2900008)) #define UMCON0 (*((volatile unsinged int*) 0xE290000C)) #define UTRSTAT0 (*((volatile unsinged int*) 0xE2900010)) #define UTXH0 (*((volatile unsinged int*) 0xE2900020)) #define URXH0 (*((volatile unsinged int*) 0xE2900004)) #define UBRDIV0 (*((volatile unsinged int*) 0xE2900028)) #define UDIVSL0T0 (*((volatile unsinged int*) 0xE290002C)) //声明函数原型 extern void uart0_init(void); extern void uart0_putc(char c); extern void uart0_puts(const char *str); extern char uart0_getc(void); #endif __UART_H__uart.m
#include "uart.h" void uart0_init(void) { //1,配置GPA0_0为串口的接收功能 //操作GPA0CON[3:0] = 0010 RXD //2 配置GPA0_1为串口的发送功能 //操作GPA0CON[7:4]= 0010 TXD GPA0CON = (GPA0CON & ~0xFF)|0x22 //3 禁止内部上下拉电阻 //操作GPAoPUD[3:0] = 0 GPA0PUD &= ~0xF; //4 配置串口寄存器 ULCON0 = 3; UCON0 = 5; UFCON0 = 0; UMCON0 = 0; UBRDIV0 = 35; UDIVSLOT0 = 0x80; } char uart0_getc(void) { //1,判断UTRSTAT0的bit[0] //bit[0] //bit[0] = 1,读取URXH0寄存器 //bit[0] = 0,等待 while(1) { if(UTRSTAT0 & 1) { break; } } //2,接收字符,读URXH0 return (URXH0 & 0xFF); } void uart0_putc(char c) { //判断状态寄存器UTRSTAT0 //bit[1] = 0,等待 //bit[1] = 1,向UTRSTAT0寄存器写数 while(!(UTRSTAT0 & 0x2)) { ; } //发送字符 UTXH0 = c; } void uart0_puts(const char *str) { if(str == 0) { return; } while(*str)// { uart0_putc(*str); str++; } }main.c
#include "uart.h" void main(void) { char ch; //1,初始化串口 uart0_init(); //2,发送一个字符串 while(1){ uart0_puts("\n URAT0 test!!!!"); //1 获取字符 ch = uart0_getc(); //2 显示接收的ch uart0_puts(ch); } }思考:如何获取字符串? 在头文件中增加声明
extern void uart0_gets(char buf[],int len);uart.m文件
void uart0_gets(char buf[],int len) { int i; for(i=0;i<len-1;i++) { //接收字符 buf[i] = uart0_getc(); } buf[i] = 0;//给字符串一个结束符号‘\0’,因为‘\0’的ASSIC码为0 }main.c
#include "uart.h" #define int BUF_LEN = 10; #define char buf[BUF_LEN]; void main(void) { char ch; //1,初始化串口 uart0_init(); //2,发送一个字符串 while(1){ uart0_puts("\n URAT0 test!!!!"); //1 获取字符串 ch = uart0_gets(buf,BUF_LEN); //2 显示接收的字符串 uart0_puts(buf); } }如何实现输入一个字符,显示一个字符?修改uart.m中的uart0_gets函数:
void uart0_gets(char buf[],int len) { int i; for(i=0;i<len-1;i++) { //接收字符 buf[i] = uart0_getc(); uart0_putc( buf[i]); } buf[i] = 0;//给字符串一个结束符号‘\0’,因为‘\0’的ASSIC码为0 }main.c
#include "uart.h" #define int BUF_LEN = 10; #define char buf[BUF_LEN]; void main(void) { char ch; //1,初始化串口 uart0_init(); //2,发送一个字符串 while(1){ uart0_puts("\n URAT0 test!!!!"); //1 获取字符串 ch = uart0_gets(buf,BUF_LEN); //2 显示接收的字符串 //uart0_puts(buf); } }如何实现当输入回车时,结束掉输入?
void uart0_gets(char buf[],int len) { int i; for(i=0;i<len-1;i++) { //接收字符 buf[i] = uart0_getc(); uart0_putc( buf[i]); if(buf[i] =='\r')//结束输入 { break; } } buf[i] = 0;//给字符串一个结束符号‘\0’,因为‘\0’的ASSIC码为0 }如何实现按delete键时,删除字符?
显示端的处理: 1,光标先左移一次 2,输出一个空格键 3,光标再次左移一次
buf处理: 调整下标i值,使得下一次的输入是原来删除字符的下标位置
void uart0_gets(char buf[],int len) { int i; for(i=0;i<len-1;i++) { //接收字符 buf[i] = uart0_getc(); if(buf[i] == '\b' || buf[i] == 127)//输入为删除键或backspace臽 { i--; if(i<0) { continue;//结束本次循环,继续下一次循环 } uart0_putc('\b');//输出一个删除键(把光标左移一位) uart0_putc(' ');//输出一个空格 uart0_putc('\b');//输出一个删除键(把光标左移一位) i--; continue; } uart0_putc( buf[i]); if(buf[i] =='\r')//结束输入 { break; } } buf[i] = 0;//给字符串一个结束符号‘\0’,因为‘\0’的ASSIC码为0 }如何把上面的串口相关的函数与前面的led做成一个shell?通过输入shell命令来打开或关闭led灯 要实现的功能为?
shell#led //点灯 shell#ledoff //关灯led.h
//寄存器定义略 extern void led_init(void); extern void led_on(void); extern void led_of(void);led.c文件
#include "led.h" void led_init(void) { //1,配置GPC1_3为输出功能 GPC1CON= (GPC1CON & 0xFFFF0F)| 0x00001000; //2,禁止GPC1_3内部上下拉电阻 GPC1PUD &= ~0xC0; } void led_on(void) { //操作GPC1DAT bit[3] =1 GPC1DAT |= 8; } void led_off(void) { //操作GPC1DAT bit[3] = 0 GPC1DAT &= ~8; }strcmp.h
#ifndef __STRCMP_H__ #define __STRCMP_H__ extern int my_strcmp(const char *str1,const char *str2); #endifstrcmp.c
#include "strcmp.h" //两个字符串比较,相等返回0,不等,返回非0 my_strcmp(const char *str1,const char *str2) { while(*str1)//因为字符串的结束符号为'\0',而它的ASSIC码为0 { if(*str1 != *str2) { return (int(*str1 - *str2));//两个的ASSIC码相减 } str1++; str2++; } return (int(*str1 - *str2)); }main.c
#include "uart.h" #include "strcmp.h" #include "led.h" #define int BUF_LEN = 10; #define char buf[BUF_LEN]; void main(void) { char ch; //1,初始化串口 uart0_init(); led_init(); //2,发送一个字符串 while(1){ uart0_puts("\n Shell#"); //1 获取字符串 ch = uart0_gets(buf,BUF_LEN); if(my_strcmp(buf,"ledon")) { //调用点灯函数 led_on(); } else { if(my_strcmp(buf,"ledoff")) { //调用关灯函数 led_off(); } } } }makefile文件略
以上代码存在一个问题,如果有很多命令的时候,采用if 比较会变得非常繁琐,增加命令很不方便。 采用结构体优化后的代码,先定义头文件,cmd.h文件如下:
#ifndef __CMD_H__ #define __CMD_H__ typedef void (*cb_t)(void); //函数指针 typedef struct _cmd { const char *name;//命令名 cb_t call_back; }cmd_t //返回的是一个结构体的地址,通过结构调用callback extern const cmd_t *find_cmd(const char *name); #endifcmd.c
#include "cmd.h" #include "led.h" void cmd_ledon(void) { //调用开灯函数 led_on(); } void cmd_ledoff(void) { //调用关灯函数 led_off(); } const cmd_t cmd_tb1[] = { {"ledon",cmd_ledon}, {"ledoff",cmd_ledoff}, }; cmd_t *find_cmd(const char *name) { }