蓝桥杯单片机开发及应用-基础模块12-串口通信(字符串)

目录

一、所要实现的功能
二、部分代码解释
三、代码实现
        1.参数定义
        2.138译码器通道选择函数
        3.初始化系统
        4.串口初始化函数
        5.串口发送函数
        6.字符串发送函数
        7.串口接收函数
        8.数据处理函数
        9.完整代码
四、运行图片

关于串口通信、中断、共阳数码管以及定时器都在之前的文章介绍过了,此处不再介绍了。

一、所要实现的功能

        实现在波特率为9600b/s时,单片机向上位机发送单字节命令控制LED灯的亮灭。发送的命令分为四种情况:

①当发送的数据为0xa~时,无论是a5还是a6,只管高四位是否为a,这时对数据进行处理,让发送的数据最后变成0xf5(高四位全部变成1,低四位的5是a取反运算),来控制LED的亮灭;

②当发送的数据为0xb~时,只管高四位是否为b,这时对数据进行处理,让发送的数据最后变成0xf4(高四位全部变成1,低四位的4是b取反运算),来控制LED的亮灭;

③当发送的数据为0xc~时,不对LED灯进行操作,发送字符串“The system is loading…”,并且回车换行;

④当发送的数据为其他任何不为a、b、c开头的,不对LED灯进行操作,发送字符串“Error!”,并且回车换行。

二、部分代码解释

switch( get_dat & 0xf0 )	// 取出高四位,只判断高四位
{
			case 0xa0:
				HC138_Init( 4 );
				P0 = ~( ( get_dat >> 4 ) & 0x0f );
				get_dat = 0x00;
			break;
}

        这里以数据为0xa~为例:首先由前面的实现功能要求可知,我们只用判断数据的高四位是a、b、c中的某个即可,所以switch语句中我们就用“get_dat & 0xf0”,取出数据的高四位,把低四位置为0,来判断是否为a开头。然后当判断是a开头是,我们打开Y4C通道,准备控制LED灯。接着“get_dat >> 4”是把数据高四位移到低四位,那么高四位就会用0来取代,以防万一,我们再进行“& 0x0f”操作,确定将数据处理成0x0a。最后由于LED灯是0亮,1灭,所以将0x0a取反操作,变成了0xf5。

三、代码实现

        1.参数定义

#include <STC15F2K60S2.H>


// 参数定义
unsigned int get_dat = 0x00;	// 接收数据

        2.138译码器通道选择函数

// 通道选择函数
void HC138_Init( unsigned char channel )
{
	switch( channel )
	{
		case 0:
			P2 = ( P2 & 0x1f ) | 0x00;	// 0
		break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;	// Y4C
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;	// Y5C
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;	// Y6C
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;	// Y7C
		break;
	}
}

        3.初始化系统

// 初始化系统
void System_Init(void)
{
	// 关闭LED灯
	HC138_Init( 4 );
	P0 = 0xff;
 
    // 关闭蜂鸣器和继电器
	HC138_Init( 5 );
	P0 = 0xaf;		    // 1010 1111
	
    // 关闭通道选择
	HC138_Init( 0 );
}

        4.串口初始化函数

// 串口初始化
void UART_Init(void)
{
	TMOD = 0x20;	// 定时器1工作模式2
	EA = 1;
	TR1 = 1;
	
	TH1 = 0xfd;		// 波特率9600b/s所对应的TH1和TL1
	TL1 = 0xfd;
	
	SCON = 0x50;	// 串口通信模式1,允许接收控制
	ES = 1;
	AUXR = 0x00;	// 辅助寄存器,直接置为0
}

        5.串口发送函数

// 串口发送信息
void UART_Send( unsigned int dat )
{
	SBUF = dat;			// 接收到数据就传给SBUF
	while( TI == 0 );	// 还未接收到数据的时候执行空指令
	TI = 0;				// 接收到数据后接收中断标志位TI会置为1,需要软件手动清零
}

        6.字符串发送函数

// 字符串发送
void String_Send( unsigned char *str )
{
/*
字符串实际上就是数组,把一个字符串拆分成多个字符组成的,用数组对这些单个的字符分别储存。
在C语言中字符串是以“\0”结束的。
数组的调取当然就需要用到指针。
*/
	while( *str != '\0' )    // 判断字符串结尾,单个字符用单引号表示
	{
		UART_Send( *str );   // 打印打个字符
		str++;				 // 地址循环加1,打印完整字符
	}
}

        7.串口接收函数

// 串口接收信息
void UART_Receive() interrupt 4
{
	if( RI == 1 )	// 接收标志位置为1,表示收到了
	{
		RI = 0;
		get_dat = SBUF;
	}
}

        8.数据处理函数

// 数据处理
void Deal_getdat(void)
{
	if( get_dat != 0x00 )
	{
		switch( get_dat & 0xf0 )	// 取出高四位,只判断高四位
		{
			case 0xa0:
				HC138_Init( 4 );
				P0 = ~( ( get_dat >> 4 ) & 0x0f );
				get_dat = 0x00;		// 清零,执行一次直接清零,否则会一直发送
			break;
			case 0xb0:
				HC138_Init( 4 );
				P0 = ~( ( get_dat >> 4 ) & 0x0f );
				get_dat = 0x00;
			break;
			case 0xc0:
				String_Send( "The system is loading...\r\n" );	// 字符串用双引号表示
				get_dat = 0x00;
			break;
			default:
				String_Send( "Error!\r\n" );
				get_dat = 0x00;
			break;
		}
	}
}

        9.完整代码

#include <STC15F2K60S2.H>


// 参数定义
unsigned int get_dat = 0x00;	// 接收数据


// 通道选择函数
void HC138_Init( unsigned char channel )
{
	switch( channel )
	{
		case 0:
			P2 = ( P2 & 0x1f ) | 0x00;	// 0
		break;
		case 4:
			P2 = (P2 & 0x1f) | 0x80;	// Y4C
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;	// Y5C
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;	// Y6C
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;	// Y7C
		break;
	}
}


// 初始化系统
void System_Init(void)
{
	// 关闭LED灯
	HC138_Init( 4 );
	P0 = 0xff;
 
    // 关闭蜂鸣器和继电器
	HC138_Init( 5 );
	P0 = 0xaf;		    // 1010 1111
	
    // 关闭通道选择
	HC138_Init( 0 );
}


// 串口初始化
void UART_Init(void)
{
	TMOD = 0x20;	// 定时器1工作模式2
	EA = 1;
	TR1 = 1;
	
	TH1 = 0xfd;		// 波特率9600b/s所对应的TH1和TL1
	TL1 = 0xfd;
	
	SCON = 0x50;	// 串口通信模式1,允许接收控制
	ES = 1;
	AUXR = 0x00;	// 辅助寄存器,直接置为0
}


// 串口发送信息
void UART_Send( unsigned int dat )
{
	SBUF = dat;			// 接收到数据就传给SBUF
	while( TI == 0 );	// 还未接收到数据的时候执行空指令
	TI = 0;				// 接收到数据后接收中断标志位TI会置为1,需要软件手动清零
}


// 字符串发送
void String_Send( unsigned char *str )
{
/*
字符串实际上就是数组,把一个字符串拆分成多个字符组成的,用数组对这些单个的字符分别储存。
在C语言中字符串是以“\0”结束的。
数组的调取当然就需要用到指针。
*/
	while( *str != '\0' )    // 判断字符串结尾,单个字符用单引号表示
	{
		UART_Send( *str );   // 打印打个字符
		str++;				 // 地址循环加1,打印完整字符
	}
}


// 串口接收信息
void UART_Receive() interrupt 4
{
	if( RI == 1 )	// 接收标志位置为1,表示收到了
	{
		RI = 0;
		get_dat = SBUF;
	}
}


// 数据处理
void Deal_getdat(void)
{
	if( get_dat != 0x00 )
	{
		switch( get_dat & 0xf0 )	// 取出高四位,只判断高四位
		{
			case 0xa0:
				HC138_Init( 4 );
				P0 = ~( ( get_dat >> 4 ) & 0x0f );
				get_dat = 0x00;		// 清零,执行一次直接清零,否则会一直发送
			break;
			case 0xb0:
				HC138_Init( 4 );
				P0 = ~( ( get_dat >> 4 ) & 0x0f );
				get_dat = 0x00;
			break;
			case 0xc0:
				String_Send( "The system is loading...\r\n" );	// 字符串用双引号表示
				get_dat = 0x00;
			break;
			default:
				String_Send( "Error!\r\n" );
				get_dat = 0x00;
			break;
		}
	}
}




int main(void)
{
	System_Init();
	UART_Init();
	
	while(1)
	{
		Deal_getdat();
	}
}

四、运行图片

单片机串口通信接收字符串的步骤如下: 1. 初始化串口模块,确定波特率、数据位、停止位、校验位等参数。 2. 等待接收串口数据,一般使用中断方式接收数据,即设置串口接收中断函数。 3. 接收到串口数据后,将数据存储到内存中。 4. 检查接收到的数据是否为完整的字符串,判断方法可以是判断是否有结束符(如'\0')或者判断接收到的字节数是否达到预期。 5. 如果接收到完整字符串,则处理数据,完成后清空缓存区,等待下一次接收。 下面是一段接收字符串的示例代码: ```c #include <reg52.h> #include <stdio.h> #define UART_BAUDRATE 9600 // 串口波特率 #define UART_BUFFERSIZE 32 // 串口缓冲区大小 unsigned char uart_buffer[UART_BUFFERSIZE]; // 串口缓冲区 unsigned char valid_data = 0; // 有效数据长度 void uart_init() { /* 初始化串口模块 */ TMOD |= 0x20; // 定时器1工作在模式2,允许自动重装载 TH1 = 0xFD; // 波特率计算公式:TH1 = 256 - (晶振频率 / (32 * 波特率)),晶振频率为11.0592 MHz TL1 = 0xFD; PCON = 0x80; // SMOD = 1,波特率加倍 SCON = 0x50; // SCON的D7和D6位分别表示串口工作模式和接收允许位 IE = 0x90; // 开启串口中断和定时器中断 TR1 = 1; // 启动定时器1 } void uart_receive() interrupt 4 { /* 串口接收中断函数 */ if (RI) { /* 接收数据 */ unsigned char data = SBUF; if (valid_data < UART_BUFFERSIZE) { uart_buffer[valid_data] = data; valid_data++; } RI = 0; } } void main() { uart_init(); while (1) { if (valid_data > 0) { /* 接收到有效数据 */ if (uart_buffer[valid_data - 1] == '\0') { /* 数据接收完成 */ printf("Received: %s\r\n", uart_buffer); // 处理数据 valid_data = 0; // 清空缓冲区,等待下一次接收 } } } } ``` 在上面的代码中,初始化了串口模块并设置了串口接收中断函数。在主函数中,不断检查串口接收缓冲区中是否有数据,如果有数据则判断是否为完整字符串,如果是则处理数据并清空缓冲区。如果缓冲区中的数据不足以组成完整的字符串,则继续等待接收。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽小迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值