找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3|回复: 0
打印 上一主题 下一主题
收起左侧

第11章 指针基础与串口实用程序11.2

[复制链接]
跳转到指定楼层
楼主

11.2字符数组和字符指针11.2.1常量和符号常量
在程序运行过程中,其值不能被改变的量称之为常量。常量分为不同的类型,有整型常量如123100;浮点型常量3.140.56-4.8;字符型常量ab0;字符串常量a abc12341234abcd等。
整型和浮点型常量直接写的数字,字符型常量用单引号来表示一个字符,用双引号来表示一个字符串,尤其要注意aa是不一样的,后边会详细介绍。
常量一般有两种表现形式。
直接常量:直接以值的形式表示的常量称之为直接常量。上述举例都是直接常量。
符号常量:用标识符命名的常量称之为符号常量,就是为上面的直接常量再取一个名字。使用符号常量一是方便理解,提高程序可读性,更重要的是方便程序的后续维护,习惯上符号常量用大写字母和下划线来命名。
比如,可以把3.14取名为PI(即π)。再比如,前边的串口程序采用的波特率是9600,如果用符号常量来进行提前声明的话,那要修改成其它速率的话,就不用在程序中找9600修改了,直接修改声明处就可以了,两种方法举例说明。
1.const声明。比如在程序开始位置定义一个符号常量BAUD
定义形式是:const  类型  符号常量名字=常量值;
const unsigned int BAUD = 9600;      /*注意结尾有个分号*/
就可以在程序中直接把9600全部采用BAUD替换,这样如果要改波特率的话,直接在程序开头位置改一下这个值就可以了。
2.用预处理命令#define来完成。
定义形式是:#define  符号常量名  常量值
#define  BAUD  9600               /*注意结尾没有分号*/
这样定义以后,只要在程序中出现BAUD的话,意思就是完全替代了后边的9600这个数字。之前定义数码管真值表的时候,用了一个code关键字。
        unsigned char code LedChar[] = {  //数码管显示字符转换表
            0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
            0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
        };
当时说加了code之后,这个真值表的数据只能被使用,不能被改变,如果直接写LedChar[0] = 1;这样就错了。实际上code这个关键字是51单片机特有的,如果是其它类型的单片机需要写成const unsigned char LedChar[]={},自动保存到FLASH里,而51单片机只用const而不加code的话,这个数组会保存到RAM中,而不会保存到FLAHS中。
整型常量和浮点型常量比较简单,整型直接写数字,十进制如128,前边0x开头的表示是十六进制0x80,浮点型直接写带小数点的数据就可以了。
字符型常量是由一对单引号括起来的单个字符。它分为两种形式,一种是普通字符,一种是转义字符。
普通字符就是那些可以直接书写直接看到的有形的字符,比如阿拉伯数字09,英文字符Az,以及标点符号等它们都是ASCII码表中的字符,而它们在单片机中都占用一个字节的空间,其值就是对应的ASCII码值。比如a的值是97A的值是650的值是48,如果定义一个变量unsigned char a = a,那么变量a的值就是97
除了上述这些字符之外,还有一些特殊字符,它们一些是无形的,像回车符、换行符这些都是看不到的,还有一些像\这类字符它们已经有特殊用途了。针对这些特殊符号,为了可以让它们正常进入到程序代码中,C语言就规定了转义字符,它是以反斜杠(\)开头的特定字符序列,让它们来表示这些特殊字符,比如用\n来代表换行。用一个简单表格来说明一下常用的转义字符的意思,如表11-1所示。
11-1  常用转义字符及含义
字符形式
含义
\n
换行
\t
横向跳格(相当于Tab
\v
竖向跳格
\b
退格
\r
光标移到行首
\\
反斜杠字符\
\
单引号字符
\
双引号字符
\f
走纸换页
\0
空值
字符串常量是用双引号括起来的字符序列,一般称之字符串。如a1234 welcome to www.qdkingst.com等都是字符串常量。字符串常量在内存中按顺序逐个存储字符串中的字符的ASCII码值,并且特别注意,最后还有一个字符\0\0字符的ASCII码值是0,它是字符串结束标志,在写字符串的时候,这个\0是隐藏的,虽然看不到,但是实际却是存在的。所以a就比a多了一个 \0a的就占了2个字节,而 a只占一个字节。
还有就是字符串中的空格,也是一个字符,比如welcome to www.qdkingst.com一共占了28个字节的空间。其中23个字母,2.2 (空格字符)以及一个\0
11.2.2字符和字符串数组实例
定义4个数组,通过演示程序对比字符串、字符数组、常量数组的区别。
    unsigned char array1[] = "1-Hello!\r\n";
    unsigned char array2[] = {'2', '-', 'H', 'e', 'l', 'l', 'o', '!', '\r', '\n'};
    unsigned char array3[] = {51, 45, 72, 101, 108, 108, 111, 33, 13, 10};
    unsigned char array4[] = "4-Hello!\r\n";
在串口调试助手下,发送十六进制的1234,使用字符形式显示,分别往电脑上送这4个数组中对应的那个数组。程序只在起始位置做了区分,其它均没有区别。一方面通过串口调试助手观察,另外通过逻辑分析仪进行对比。
此外还要说明一点,数组1和数组4,数组1发完整的字符串,而数组4仅仅发送数组中的字符,没有发结束符号。串口调试助手用字符形式显示是没有区别的,但是如果改用十六进制显示,会发现数组1比数组4多了一个字节\0ASCII00
#include <reg52.h>
bit cmdArrived = 0;   //命令到达标志,即接收到上位机下发的命令
unsigned char cmdIndex = 0; //命令索引,即与上位机约定好的数组编号
unsigned char cntTxd = 0;   //串口发送计数器
unsigned char *ptrTxd;      //串口发送指针
unsigned char array1[] = "1-Hello!\r\n";
unsigned char array2[] = {'2', '-', 'H', 'e', 'l', 'l', 'o', '!', '\r', '\n'};
unsigned char array3[] = {51,  45,  72,  101, 108, 108, 111, 33,  13,   10};
unsigned char array4[] = "4-Hello!\r\n";
void ConfigUART(unsigned int baud);
void main()
{
    EA = 1;  //开总中断
    ConfigUART(9600);  //配置波特率为9600
   
    while (1)
    {
        if (cmdArrived)
        {
            cmdArrived = 0;
            switch (cmdIndex)
            {
                case 1:
                    ptrTxd = array1;           //数组1的首地址赋值给发送指针
                    cntTxd = sizeof(array1); //数组1的长度赋值给发送计数器
                    TI = 1;    //手动方式启动发送中断,处理数据发送
                    break;
                case 2:
                    ptrTxd = array2;
                    cntTxd = sizeof(array2);
                    TI = 1;
                    break;
                case 3:
                    ptrTxd = array3;
                    cntTxd = sizeof(array3);
                    TI = 1;
                    break;
                case 4:
                    ptrTxd = array4;
                    cntTxd = sizeof(array4) - 1; //字符串实际长度为数组长度减1
                    TI = 1;
                    break;
                default:
                    break;
            }
        }
    }
}
/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
    SCON  = 0x50;   //配置串口为模式1
    TMOD &= 0x0F;  //清零T1的控制位
    TMOD |= 0x20;  //配置T1为模式2
    TH1 = 256 - (11059200/12/32)/baud;  //计算T1重载值
    TL1 = TH1;     //初值等于重载值
    ET1 = 0;       //禁止T1中断
    ES  = 1;       //使能串口中断
    TR1 = 1;       //启动T1
}
/* UART中断服务函数 */
void InterruptUART() interrupt 4
{
    if (RI)  //接收到字节
    {
        RI = 0;  //清零接收中断标志位
        cmdIndex = SBUF;  //接收到的数据保存到命令索引中
        cmdArrived = 1;   //设置命令到达标志
    }
    if (TI)  //字节发送完毕
    {
        TI = 0;  //清零发送中断标志位
        if (cntTxd > 0)  //有待发送数据时,继续发送后续字节
        {
            SBUF = *ptrTxd;  //发出指针指向的数据
            cntTxd--;         //发送计数器递减
            ptrTxd++;         //发送指针递增
        }
    }
}
采用逻辑分析仪将4次收发数据全部抓出来,其中串口助手下发用HEX模式,而接收用文本模式,也就是ASCII码格式显示,逻辑分析仪也是这样配置,如图11-2所示。

11-2 逻辑分析仪抓取串口字符和字符串信息
从图11-2可以看出,1234多了一个结束符,其他内容4组数据是完全一致的。(CR就是\rLF就是\n

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表