蓝桥杯单片机模块概览及功能解析
本文较少涉及硬件与时序,主要从代码层面记录蓝桥杯单片机对DS1302、DS18B20、PCF8591、AT24C02模块的使用
目录
一、DS1302
二、DS18B20
三、IIC
四、PCF8591
五、AT24C02
六、NE555
七、PWM
八、超声波
九、串口
一、DS1302
硬件连接我们仅关注三个引脚:SCK(时钟信号线)、SDA(数据线、RST(芯片使能)。
寄存器:
时序图:
ds1302.c底层驱动:
#include "ds1302.h"
#include <reg52.h>
#include <intrins.h>
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
//写字节,上升沿有效
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;//从低位一位一位向右移动
temp>>=1;
SCK=1;
}
}
//向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address); //传入地址(一个字节)
Write_Ds1302(dat); //后传入数据(一个字节)
RST=0;
}
//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);//写入地址
for (i=0;i<8;i++) //写入数据,上升沿有效,数据先来 上升沿后来
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80; //从高位到低位,一位一位右移
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
需要我们在DS1302.c写的函数:
//向芯片写入时分秒
void Set_Rtc(unsigned char* ucRtc)
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);//关闭写保护:向0x8E写入0x00
for(i=0;i<3;i++)//依次写入时分秒
Write_Ds1302_Byte(0x84-2*i,ucRtc[i]);//地址依次为0x84,0x82,0x80
Write_Ds1302_Byte(0x8e,0x80);//打开写保护:向0x8E写入0x80
}
//读出芯片的时分秒
void Read_Rtc(unsigned char* ucRtc)
{
unsigned char i;
for(i=0;i<3;i++)//依次读出时分秒
ucRtc[i] = Read_Ds1302_Byte(0x85-2*i);//地址依次为0x85,0x83,0x81
}
主函数的处理:
#include <ds1302.h>//时钟驱动专用头文件
...
...
...
unsigned char ucRtc[3] = {0x23,0x59,0x55};//时钟数据存放数组 默认时间 23:59:55
...
...
...
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
/* 信息读取区域 */
Read_Rtc(ucRtc);//实时读取时钟数据
/* 数据处理区域 */
Seg_Buf[0] = ucRtc[0] / 16;
Seg_Buf[1] = ucRtc[0] % 16;
Seg_Buf[2] = 11;//Seg_Dula[11]=0xbf,代表间隔符
Seg_Buf[3] = ucRtc[1] / 16;
Seg_Buf[4] = ucRtc[1] % 16;
Seg_Buf[5] = 11;
Seg_Buf[6] = ucRtc[2] / 16;
Seg_Buf[7] = ucRtc[2] % 16;
}
void main()
{
System_Init();
Timer0Init();
Set_Rtc(ucRtc);//上电时设置时间
while (1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
注:由于DS1302存储数据的形式是8421BCD码,而数码管显示的形式是十进制(若第i个数码管显示9,Seg_Buf[i]=9),所以存在一个问题:若不进行转换,9(0000 1001)结束后显示16(0001 0000).
8421BCD码转十进制:DEC=BCD/16*10+BCD%16(2位BCD)
十进制转8421BCD码:BCD=DEC/10*16+DEC%10(2位BCD)
所以,在DS1302数据显示时,进行/16、%16操作;而在往DS1302写数据时ucRtc[]内的数据即为8421BCD码。
二、DS18B20
硬件连接我们仅关注DQ(数据通信线,外接上拉电阻)
高速暂存器(9个字节)
第0、1字节:
高五位为符号位,温度为正S=1;温度为负S=0。
配置寄存器:
初始化时序:
读写时序:
ds18b20.c底层代码:
#include "onewire.h"
#include "reg52.h"
sbit DQ = P1^4;
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
t*=12;//如果不写这一句的话,上电温度显示55.9
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;//从低位到高位一位一位写
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;//从高位到低位一位一位写
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ; //0表示初始化成功
Delay_OneWire(5);
return initflag;
}
ds18b20.c需要我们写的函数:
/*DS18B20温度读取函数*/
float read_t()
{
unsigned char low,high;//返回温度数据的高低八位
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//进行温度转换
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);//读取温度
low = Read_DS18B20();//读取低位
high = Read_DS18B20();//读取高位
return ((high << 8) | low) / 16.0;
}
主函数处理:
#include "onewire.h"
...
...
...
float t;
...
...
...
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
t = read_t();//获取温度
Seg_Buf[0] = (unsigned char)t / 10 % 10;//显示读取温度的十位
Seg_Buf[1] = (unsigned char)t % 10;//显示读取温度的个位
Seg_Buf[2] = (unsigned int)(t * 10) % 10;//显示读取温度的小数第一位
}
...
...
...
void main()
{
read_t();//上电读取温度,防止显示“85”
Delay750ms();
System_Init();
Timer0Init();
while (1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
三、IIC
不同IC双向通信,串行数据线(SDA)和串行时钟线(SCL)外接上拉电阻。
底层代码:
#include "iic.h"
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;//从高位到低位,一位一位左移
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;从低位到高位一位一位左移
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
在起始信号和结束信号中,SCL始终为高电平SDA跳变。所以在数据位传输期间当数据交换时需要把SCL拉低,否则当SCL=1,SDA的任何跳变都会被认为是总线信号的起始和暂停。
四、PCF8591
我们仅关注:地址线A0、A1、A2接地;ADC输入引脚AIN0、AIN1、AIN2、AIN3(AIN1接光敏电阻,AIN3接滑动变阻器);IIC通信引脚SCL、SDA。
地址:A2、A1、A0=0,读地址为0x91,写地址为0x90.
控制字:D1、D0为AD通道,00通道1、01通道1、10通道2、11通道3;D5、D4为模拟量输入选择:一般选择00(四路单输入);D2自动增益默认1;D6模拟输出允许默认1.
光敏电阻为0x41,滑动变阻器为0x43
IIC.c中需要我们写的AD、DA函数
//函数名:ADC转换函数
//入口参数:要进行转换的通道控制位
//返回值:ADC转换的数值
//函数功能:对指定的通道进行ADC转换,函数返回转换的数值
unsigned char AD_Read(unsigned char channel_num_contrl)
{
unsigned char temp;
/*读*/
IIC_Start();//发送开启信号
IIC_SendByte(0x90);//选择PCF8591芯片,确定写的模式
IIC_WaitAck();//等待PCF8591反馈
IIC_SendByte(channel_num_contrl);//确定要转换的通道(顺便,使能DA转换)
IIC_WaitAck();//等待PCF8591反馈
/*写*/
IIC_Start();//发送开启信号
IIC_SendByte(0x91);//选择PCF8591芯片,确定读的模式
IIC_WaitAck();//等待PCF8591反馈
temp = IIC_RecByte();//接收数据
IIC_SendAck(1);//选择不应答
IIC_Stop();//停止发送
return temp;
}
//函数名:DAC转换函数
//入口参数:要进行转换的数值
//返回值:无
//函数功能:对入口参数要转换的DA数据进行转换
void DA_Write(unsigned char trans_dat)
{
IIC_Start();//发送开启信号
IIC_SendByte(0x90);//选择PCF8591芯片,确定写的模式
IIC_WaitAck();//等待PCF8591反馈
IIC_SendByte(0x41);//使能DA转换(随便写通道编号,保证控制字D6为1即可,主要的功能是使能DA)
IIC_WaitAck();//等待PCF8591反馈
IIC_SendByte(trans_dat);//将待转换的数据发送出去
IIC_WaitAck();//等待PCF8591反馈
IIC_Stop();//停止发送
}
主函数的处理:
#include <iic.h>//数模转换底层驱动专属头文件
...
...
...
float Voltage;//实时读取电压值,AD
...
...
...
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
/* 数据读取区域 */
Voltage = AD_Read(0x43) / 51.0;//读取实时电压值
DA_Write(127);//实时输出电压值
/* 信息显示区域 */
//AD读取值,数码管显示x.xx
Seg_Buf[0] = (unsigned char)Voltage;
Seg_Buf[1] = (unsigned int)(Voltage * 100) / 10 % 10;
Seg_Buf[2] = (unsigned int)(Voltage * 100) % 10;
}
若AD1读取光敏电阻(0x41)的值,AD2读取滑动变阻器(0x43)的值,在main.c中不写
AD1=Ad_Read(0x41);AD2=Ad_Read(0x43);
而是写:AD1=Ad_Read(0x43);AD2=Ad_Read(0x41);
五、AT24C02
硬件连接我们仅关注:地址线E0、E1、E2均为0,写保护WE=0,IIC通信线SCL、SDA。
设备地址字:该EERROM存储空间为2K,A2=A1=A0=0。读地址为0xA1,写地址为0xA0。
需要在iic.c写的EEPROM的函数:
//函数名:写EEPROM函数
//入口参数:需要写入的字符串,写入的地址(务必为8的倍数),写入数量
//返回值:无
//函数功能:向EERPOM的某个地址写入字符串中特定数量的字符。
void EEPROM_Write(unsigned char* EEPROM_String, unsigned char addr, unsigned char num)
{
IIC_Start();//发送开启信号
IIC_SendByte(0xA0);//选择EEPROM芯片,确定写的模式
IIC_WaitAck();//等待EEPROM反馈
IIC_SendByte(addr);//写入要存储的数据地址
IIC_WaitAck();//等待EEPROM反馈
while(num--)
{
IIC_SendByte(*EEPROM_String++);//将要写入的信息写入
IIC_WaitAck();//等待EEPROM反馈
IIC_Delay(200);
}
IIC_Stop();//停止发送
}
//函数名:读EEPROM函数
//入口参数:读到的数据需要存储的字符串,读取的地址(务必为8的倍数),读取的数量
//返回值:无
//函数功能:读取EERPOM的某个地址中的数据,并存放在字符串数组中。
void EEPROM_Read(unsigned char* EEPROM_String, unsigned char addr, unsigned char num)
{
IIC_Start();//发送开启信号
IIC_SendByte(0xA0);//选择EEPROM芯片,确定写的模式
IIC_WaitAck();//等待EEPROM反馈
IIC_SendByte(addr);//写入要读取的数据地址
IIC_WaitAck();//等待EEPROM反馈
IIC_Start();//发送开启信号
IIC_SendByte(0xA1);//选择EEPROM芯片,确定读的模式
IIC_WaitAck();//等待EEPROM反馈
while(num--)
{
*EEPROM_String++ = IIC_RecByte();//将要写入的信息写入
if(num) IIC_SendAck(0);//发送应答
else IIC_SendAck(1);//不应答
}
IIC_Stop();//停止发送
}
主函数的处理:
#include "iic.h"
...
...
...
unsigned char dat[2] = {30,60};
unsigned char a = 200;
...
...
...
/* 键盘处理函数 */
void Key_Proc()
{
if(Key_Slow_Down) return;
Key_Slow_Down = 1;//键盘减速程序
Key_Val = Key_Read();//实时读取键码值
Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);//捕捉按键上降沿
Key_Old = Key_Val;//辅助扫描变量
switch(Key_Down)
{
case 19:
a += 10;
break;
case 18:
dat[1] -= 10;
break;
case 17:
EEPROM_Write(dat,0,2);
break;
case 16:
EEPROM_Write(&a,0,1);
break;
}
}
...
...
...
/* 信息处理函数 */
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
Seg_Buf[0] = a / 100 % 10;
Seg_Buf[1] = a / 10 % 10;
Seg_Buf[2] = a % 10;
Seg_Buf[6] = dat[1] / 10;
Seg_Buf[7] = dat[1] % 10;
}
...
...
...
void main()
{
EEPROM_Read(&a,0,1);
EEPROM_Read(dat,0,2);
System_Init();
Timer0Init();
while (1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
第一次烧录前将主函数的读出函数删除(注释),烧录后修改变量的值并保存到EEPROM中。断电,将主函数的读出函数加上,上电后显示的变量为修改后的变量。
由于EEPROM读写数据以字节为单位,所以在使用中尽量使用char型。
六、NE555
由原理图可知,NE555的输出引脚OUT连接NET SIG,当使用跳线帽连接P34引脚后,使用定时器1作为定时器(中断号为3)进行1ms定时,使用定时器0作为计数器记录脉冲上升沿。
在TIM0的TMOD中,GATE配置为0,C/T配置为1,M1、M0配置为01模式,即16位不可重装载模式。TMOD0=0101.
使用STC—ISP对定时器0进行如下配置
不需要进行定时器0中断修改代码为(将TMOD |= 0x01;修改为TMOD |= 0x05;)
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置计数模式
TL0 = 0; //设置定时初始值
TH0 = 0; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
注意:(1)频率值定义为int型(必超255)(2)定时器中断号为3 (3)TH0、TL0的值需要手动归零
unsigned int Timer_1000Ms;//1000毫秒计时变量
unsigned int Freq;//实时频率值
void Timer1Server() interrupt 3
{
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;//数码管减速专用
if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
if(++Timer_1000Ms == 1000) //实时读取频率值
{
Timer_1000Ms = 0;
Freq = TH0 << 8 | TL0;
TH0 = TL0 = 0;
}
}
七、PWM
一般要求设置20%这样的占空比,可考虑在定时器中断中使一个count变量从0到9往复循环,定义一个阈值例如2,可以在一个周期内进行两个变量的比较,例如低于阈值输出1高于阈值输出0,以此在极短的时间内从宏观上控制功率。
下面以P34引脚输出不同占空比、频率为1kHz的PWM为例:
由于频率为1kHz(要实现定时器里的count变量从0到9,定时器的周期要0.1ms)而定时器0的周期为1ms,所以需要重新使能另一个定时器。
void Timer1Init(void) //100微秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x9C; //设置定时初值
TH1 = 0xFF; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
}
void Timer1Server() interrupt 3
{
if(work_time != 0)
{
if(++pwm_count == 10) pwm_count = 0;
switch(wind_mode)
{
case 0:
pwm_level = 2;
break;
case 1:
pwm_level = 3;
break;
case 2:
pwm_level = 7;
break;
}
if(pwm_count >= pwm_level) P34 = 0;
else P34 = 1;
}
}
使能定时器1 中断,每0.1ms进入一次中断实现pwm_count++,根据pwm_count和pwm_level的大小关系,给P34电平的高和低。
八、超声波
J2跳线帽选1-3 3-5,一般选用定时器1作为信号测量。发送引脚TX,接受引脚RX。
#include <ultrasonic.h>
#include <intrins.h>
sbit Tx = P1^0;
sbit Rx = P1^1;
void Delay12us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 38;
while (--i);
}
void Wave_Init()
{
unsigned char i;
for(i=0;i<8;i++)
{
Tx = 1;
Delay12us();
Tx = 0;
Delay12us();
}
}
unsigned int Ut_Wave_Data() //超声波距离读取函数
{
unsigned int time;//时间储存变量
CMOD = 0x00;//配置PCA工作模式
CH = CL = 0;//复位计数值 等待超声波信号发出
Wave_Init();//发送超声波信号
CR = 1;//开始计时
while((Rx == 1) && (CF == 0));//等待接受返回信号或者定时器溢出
CR = 0;//停止计时
if(CF == 0) //定时器没有溢出
{
time = CH << 8 | CL;//读取当前时间
return (time * 0.017);//返回距离值
}
else
{
CF = 0;//清除溢出标志位
return 0;
}
}
初始化TX产生8个40KHz的方波信号,开启定时器计时,接收到超声波信号返回后关闭定时器。默认声速340m/s,距离=时间*0.017(cm)
main.c的使用
unsigned char Wave_Data;
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
Wave_Data = Ut_Wave_Data();
Seg_Buf[0] = Wave_Data / 100 % 10;
Seg_Buf[1] = Wave_Data / 10 % 10;
Seg_Buf[2] = Wave_Data % 10;
}
九、串口
配置如下:
添加“ES=1;EA=1”
uart.c如下:
#include <Uart.h>
/* 串口初始化函数 */
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xC7; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1;
EA = 1;
}
/* 字节发送函数 */
void SendByte(unsigned char dat)
{
SBUF=dat;//将dat数据赋给SBUF,将数据发送出去
while(TI == 0);//等待数据发送
TI = 0;//将发送标志位清零
}
/* 字符串发送函数 */
void Uart_Send_String(unsigned char *dat)
{
while(*dat != '\0')//当字符不为空时,继续发送
SendByte(*dat++);//发送后指针dat加1,指向下一个字节
}
由于定时器0负责三大模块的扫描与其他变量的计数,定时器1负责超声波或NE555的计数,故使用定时器2作为波特率发生器。
main.c处理:
#include <Uart.h>//串口底层驱动专用头文件
#include <stdio.h>
unsigned char Uart_Slow_Down;//串口减速专用变量
unsigned char Uart_Recv[10];//串口接收数据储存数组 默认10个字节 若接收数据较长 可更改最大字节数
unsigned char Uart_Recv_Index;//串口接收数组指针
unsigned char Uart_Send[10];//串口接收数据储存数组 默认10个字节 若发送数据较长 可更改最大字节数
unsigned char dat;
void Key_Proc()
{
if(Key_Slow_Down) return;
Key_Slow_Down = 1;//键盘减速程序
Key_Val = Key_Read();//实时读取键码值
Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);//捕捉按键上降沿
Key_Old = Key_Val;//辅助扫描变量
switch(Key_Down)
{
case 4:
sprintf(Uart_Send,"T = %.2f\r\n",t);
Uart_Send_String(Uart_Send);
break;
}
}
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//数码管减速程序
t = rd_temperature();
Seg_Buf[0] = dat / 10;
Seg_Buf[1] = dat % 10;
}
void Uart_Proc()
{
if(Uart_Slow_Down) return;
Uart_Slow_Down = 1;//串口减速程序
if(Uart_Recv_Index == 6)
{
if(Uart_Recv[0] == 'L' && Uart_Recv[1] == 'e' && Uart_Recv[2] == 'd' && Uart_Recv[4] == '=')
ucLed[Uart_Recv[3] - 48] = Uart_Recv[5] - 48;
Uart_Recv_Index = 0;
}
}
void Uart1Server() interrupt 4
{
if(RI == 1) //串口接收数据
{
Uart_Recv[Uart_Recv_Index] = SBUF;
Uart_Recv_Index++;
RI = 0;
}
}
void main()
{
System_Init();
Timer0Init();
UartInit();
while (1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
Uart_Proc();
}
}
按下S4向串口发送一次温度数据,在接受缓冲区显示。在发送缓冲区输入“Ledi=x”可改变LED状态。
作者:Auroraisme