1 回顾
串口通信的代码编写结构还是与中断一样,不同的是:
初始中断函数条件涉及到串口通信相关的寄存器和定时器1相关的寄存器(定时器1用于产生波特率),但初始条件中的中断寄存器只考虑串口通信而不考虑定时器1。
void 函数名()
{
包含两部分寄存器:定时器1+串口通信
定时器1: TMOD (选择模式),TH1和TL1(初始计时寄存器),TR1(TCON寄存器里的启动计时按钮)
串口通信:SCON(总的来说功能是模式选择),AUXR(辅助寄存器),中断开关(分开关+总开关)
}
void 函数名() interrupt 中断号
{
就是写时间到后执行什么。注意中断号要写串口通信的,而不是定时器的,因为定时器作用只是产生波特率而不是产生中断。
}
2 C语言字符串知识补充:
字符串的C语言知识发现自己还不是很懂,就简单写一下。
常用的有两种,一种是字符串常量,一种是字符串数组。
判断字符串中止的标志是“\0 ”,表示NULL。
2.1 字符串常量
公式:char *(+指针名称如A)= “ 字符串常量内容”
表示在A指针所对应的往下连续地址中,储存字符串常量。
char *message = "Hello World!";// 上面的语句也可以拆分成下面两句
char *message;
message = "Hello World!";
2.2 字符串数组
char charArray[] = {'H','e','l','l','o'}; // 声明并初始化一个字符数组
char charArray[] = "Hello World!";
以上参考以下帖子,详情可点击进去查看。
C语言 -- 字符串详解 - 知乎 (zhihu.com)
3 实践
3.1 任务
3.2 思路
读题目是串口通信———那么就要写串口通信的结构
采用8位UART模式,波特率9600--------这些条件就可以确定串口通信结构的中断初始函数怎么写(NO9串口通信实践的另一篇有详细说明这里就不再赘述)
void Init_uart()
{TMOD = 0x20;TH1 = 0xfd;TL1 = 0xfd;TR1 = 1;AUXR = 0x00;SCON = 0x50;ES = 1;EA = 1;}
要上上位机发送,故要写一个发送函数,又是字符串,那么就要利用2的字符串知识补充来写。
这里字符串是一个字符接一个字符来发的(但速度较快看起来就是一下子发了出来),而 while(*str != '\0') 是判断字符串是否发完了,如果没发完,那么字符串的指针就加1,即一个一个字节来发。
void SentByte(unsigned char dat)
{SBUF = dat;while(TI == 0);TI = 0;
}void SentString(unsigned char *str)
{while(*str != '\0'){SentByte(*str++);}}
通过串口发送的接收命令来进行控制操作,那么就需要一个收的操作,并且还要写一个函数来判断并执行不同命令。
这里就主要将以下这个判断命令的思路。
命令分三种,是0xa_ , 0xb_ ,和0xc0,a,b,c来判断哪一种命令,低四位则代表这种命令的相关操作。
首先就要区别abc哪一种命令,这里可以用command来储存收到的命令,用command & 0xf0 来判断是a还是b还是c,与上0xf0,即是保留command高四位去掉低四位,那么command要么是0xa0要么是0xb0要么是0xc0,然后再用一个switch-case来存放三种命令的情况。
case里面放置三种命令的具体执行。
case(0xa0):是要用command的低四位去控制灯(L1~L4),注意这里1是开灯,0是关灯。(而单片机本身是0才亮灯。)
这里用这个公式来执行此命令: P0 = ~(command & 0x0f); break;
分析:command先与上0x0f,表示command高四位清零,低四位保留,然后在取反。
比如 command = 0xa3(1010 0011),表示L1和L2点亮。
1010 0011
&
0000 1111
=
0000 0011
然后~(0000 0011) = 1111 1100, 而在单片机上恰好和命令相反是0时灯才亮,所以就完成了。
(注意,判断哪种命令时使用了command&0xf0,并没有改变command的值,因为它是在switch条件里的switch(command & 0xf0)的操作,而不是command = command &0xf0,所以这里并没有改变command的值。)
case(0xb0):这里就不再解释0xb0了,和0xa0的操作思路差不多。
case(0xc0):此命令是发送字符串,那么就用到了写的sentByte函数,注意这里发送完后command要清零,不然就会循环发送字符串。
unsigned char dat;
unsigned char command = 0x00;
void Service_uart() interrupt 4
{if (RI == 1) 收操作{command = SBUF;RI =0;}}void Working() 判断并执行命令
{if(command != 0x00){switch(command & 0xf0){case(0xa0):P0 = ~(command & 0x0f); break;case(0xb0):P0 = ~((command & 0x0f)<<4); break;case(0xc0):SentString("The system is running...\n"); command = 0x00; break; }}
}
3.3 完整代码
#include "stc15f2k60s2.h"void selectHC138(unsigned int n)
{switch(n){case 0:P2 = (P2 & 0x1f) | 0x00; break;case 1:P2 = (P2 & 0x1f) | 0x20; break;case 2:P2 = (P2 & 0x1f) | 0x40; break; case 3: P2 = (P2 & 0x1f) | 0x60; break; case 4:P2 = (P2 & 0x1f) | 0x80; break; case 5:P2 = (P2 & 0x1f) | 0xa0; break; case 6:P2 = (P2 & 0x1f) | 0xc0; break; case 7:P2 = (P2 & 0x1f) | 0xe0; break;}
}
//==================================
void Init_uart()
{TMOD = 0x20;TH1 = 0xfd;TL1 = 0xfd;TR1 = 1;AUXR = 0x00;SCON = 0x50;ES = 1;EA = 1;}unsigned char dat;
unsigned char command = 0x00;
void Service_uart() interrupt 4
{if (RI == 1){command = SBUF;RI =0;}}void SentByte(unsigned char dat)
{SBUF = dat;while(TI == 0);TI = 0;
}void SentString(unsigned char *str)
{while(*str != '\0'){SentByte(*str++);}}void Working()
{if(command != 0x00){switch(command & 0xf0){case(0xa0):P0 = ~(command & 0x0f); break;case(0xb0):P0 = ~((command & 0x0f)<<4); break;case(0xc0):SentString("The system is running...\n"); command = 0x00; break; }}
}//===============================void close()
{selectHC138(5);P0 = 0x00;selectHC138(4);P0 = 0xff;
}void main()
{close();Init_uart();SentString("Welcome to system!\n");while(1){Working();}
}