ARM第五天(串口下)

这里写图片描述

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)
{

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值