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);
#endif
strcmp.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);
#endif
cmd.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)
{
}