NO9 蓝桥杯单片机串口通信之进阶版

发布于:2024-03-29 ⋅ 阅读:(13) ⋅ 点赞:(0)

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();
  }
}

本文含有隐藏内容,请 开通VIP 后查看