串口收发字符串

1. 串口初始化

        串口初始主要涉及如下几个参数:时钟频率,波特率,产生波特率的定时器,但其实这些内容都不需要我们操心,在软件点两下就好了,下文Code1的串口配置如图1所示。需要注意的是,低版本的stcai-isp软件没有打通中断通道,需要使用者自行配置串口中断(ES=1;EA=1;)。

        请注意,若是你使用了STC12或IAP15等宏晶科技的芯片,却使用<reg52.h>等作为头文件,将会在寄存器AUXR处发生报错。解决方法也很简单,只需要定义一个寄存器即可。如Code2。

图1

void Uart1_Init(void)	//9600bps@11.0592MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器时钟1T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0xE0;			//设置定时初始值
	TH1 = 0xFE;			//设置定时初始值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
	ES = 1;				//使能串口1中断
    EA = 1;             //开启总中断
}

Code1

sfr AUXR  = 0x8E; 

void Uart1_Init(void)	//9600bps@11.0592MHz
{
...代码省略,参考Code1...
}

Code2

2. 串口发送字符串

        串口接收比发送困难,因此先讲串口发送。无论什么数据类型都可以转为字符串发送,因此这里主讲串口发送字符串。

        首先编写一个发送函数UartSendString()。如Code3。该函数主要有两种使用方法,方法1:直接发送一个固定字符串,如Code4;方法2:使用sprintf函数生成字符串,如Code5。

        下面主要讲一下Code5:

        (1)stdio.h包含了sprintf函数,生成字符串需要sprintf函数。

        (2)为什么要将unsigned char 类型的soundNow转化为unsigned int,而不是直接使用它本身?因为我们希望将125传到PC端,而不是125对应的ASCLL对应的'}'。因此需要将其转为unsigned int类型,然后使用%d进行占位。

        (3)为什么要将float类型的lightNow拆分成%d.%d,而不是直接使用%.2f进行占位?原因是:若使用%.2f进行占位操作后,如果后面还有其他数据,那么这些数据会乱码。举个例子"a is %.2f and b is 23",这个and b is 23就有可能乱码。具体为什么会乱码,我也不知道,也不知道怎么解决这个乱码,只能绕路了。

void UartSendString(const unsigned char *da)
{
    unsigned char i=0;
    while(da[i] != '\0')
    {
        SBUF = da[i];
        while(TI==0) ;
        TI=0;
        i++;
    }
}

Code3

UartSendString("Hello World!");

Code4

// 导入必要的头文件
#include <stdio.h>


// 生成一些数据
unsigned char soundNow = 125;
unsigned int temNow = 59;
float lightNow = 93.48;

// 数组,用于储存字符串数据
unsigned char dataToSend[100];

// 生成字符串,并发送,需要注意数组是否越界
sprintf(dataToSend, "The sound is %d!\n", (unsigned int)soundNow);
UartSendString(dataToSend);

sprintf(dataToSend, "The tem is %d!\n", temNow);
UartSendString(dataToSend);

sprintf(dataToSend, "The light is %d.%d!\n", (unsigned int)lightNow, (unsigned int)((unsigned int)(lightNow*100)%100));
UartSendString(dataToSend);

Code5

3. 串口接收数据

        数据可能有多种格式:

        (1)比如一次只接收1个HEX数据(如Code6),每个数据都代表了一个特定意思,这种是最简单的;

        (2)进阶一点:(使用包头包尾)接收固定长度数据,比如Led1=1;Led2=0;

        (3)更进一步:使用包头包尾接收不固定长度的数据,如##You good!@@,其中##为包头,@@为包尾,主要使用了状态机思想,具体请移步up主江协科技stm32视频。Code7供参考。

// 全局变量,接收数据
unsigned char da=0;

void Uart_Interrupt(void) interrupt 4
{
    if(RI)
    {
        RI=0;
        da=SBUF;
    }
}

Code6

unsigned char ReceiveData[10];
bit ReceiveDoneFlag = 0;

void Uart_Interrupt(void) interrupt 4
{
    static unsigned char stata=0, i=0;
    unsigned char da=0;
    if(RI)
    {
        RI=0;
        da=SBUF;
        if(stata==0)
        {
             if(da=='#') stata = 1;
             else stata = 0;
        }
        else if(stata==1)
        {
            if(da=='#') stata=2;
            else stata=0;
        }
        else if(stata==2)
        {
            if(da=='@') stata=3;
            else
            {
                ReceiveData[i]=da;
                i=(i+1)%10;
            }
        }
        else if(stata==3)
        {
            if(da=='@')
            {
                stata=0;
                //ReceiveData[i]='\0';
                i=0;
                ReceiveDoneFlag=1;
            }
            else 
            {
                ReceiveData[i]='@';
                i=(i+1)%10;
                ReceiveData[i]=da;
                i=(i+1)%10;
                stata = 2;
            }
        }
    }
}

Code7

下面是一个简单的示例代码,实现51单片机通过串口接收字符串: ```c #include <reg51.h> #define FOSC 11059200L // 定义晶振频率 #define BAUD 9600 // 定义波特率 #define MAX_LEN 20 // 定义接收的最大长度 unsigned char RxdBuf[MAX_LEN]; // 定义接收缓冲区 unsigned char RxdLen = 0; // 定义接收长度 void InitUART() // 初始化串口 { SCON = 0x50; // 设置串口工作方式 TMOD &= 0x0F; // 清除T1工作方式 TMOD |= 0x20; // 设置T1为模式2 TH1 = TL1 = -(FOSC / 12 / 32 / BAUD); // 计算T1重载值 TR1 = 1; // 启动T1计数器 ES = 1; // 使能串口中断 EA = 1; // 使能总中断 } void UART_Isr() interrupt 4 // 串口中断处理函数 { if (RI) // 如果收到数据 { RI = 0; RxdBuf[RxdLen] = SBUF; // 将数据存入接收缓冲区 if (RxdBuf[RxdLen] == '\0') // 如果接收到字符串结束符 { RxdLen = 0; // 清空接收长度 } else if (RxdLen < MAX_LEN - 1) // 如果接收长度未达到最大值 { RxdLen++; // 接收长度加1 } } } void main() { InitUART(); // 初始化串口 while (1) { if (RxdLen > 0) // 如果接收到数据 { // 处理接收到的字符串 // ... RxdLen = 0; // 清空接收长度 } } } ``` 这段代码通过中断方式接收串口数据,并将数据存入接收缓冲区。当接收到字符串结束符时,将会清空接收长度,并可以对接收到的字符串进行处理。需要注意的是,由于51单片机的RAM较小,所以接收缓冲区大小需要适当设置,以免超出RAM容量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值