目录
一、所要实现的功能
二、部分代码解释
三、代码实现
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();
}
}