main.c(54): warning C316: unterminated conditionals
头文件中
#ifndef
#define
#endif 写错了
main.c(32): warning C182: pointer to different objects
容易出现在EEPROM里面
*** ERROR L107: ADDRESS SPACE OVERFLOW
SPACE: DATA
SEGMENT: ?DT?SEG
LENGTH: 0019H
*** ERROR L105: PUBLIC REFERS TO IGNORED SEGMENT
SYMBOL: NUMBER
SEGMENT: ?DT?SEG
*** ERROR L105: PUBLIC REFERS TO IGNORED SEGMENT
SYMBOL: LOCATION
SEGMENT: ?DT?SEG
Program Size: data=107.1 xdata=0 code=3554
注意idata爆满不会报错但是会对程序有影响
xdata和pdata 变量一定要进行初始化 因为他们的默认值并不是0
idata unsigned char i=0;
pdata unsigned char i=0;
xdata unsigned char i=0;
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: SYSTEM_INIT
MODULE: .\Objects\Init.obj (INIT)
头文件改Init.h
main.c(108): error C193: '': bad operand type
强制类型转换
main.c(28): warning C206: 'Seg': missing function-prototype
main.c(28): error C267: 'Seg': requires ANSI-style prototype
或者MDK和C51没有装一起
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: INTO_DAT_OLD
MODULE: .\Objects\main.obj (MAIN)
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: INTO_DAT
MODULE: .\Objects\main.obj (MAIN)
可以在一个变量加上一个字母
..\Driver\Led.c(7): error C202: 'temp_Old': undefined identifier
..\Driver\Led.c(10): error C202: 'temp_Old': undefined identifier
..\Driver\Led.c(15): error C202: 'temp_Old': undefined identifier
temp_Old没有定义
如果接了跳线帽到P34给NE555外部晶振也会影响按键P34列的使用
因为脉冲就是高低电平的转化
而且最好不要定义P34赋值按键
因为P34用来频率扫描
这个就是意味着temp值的局部变量刷新
最好不要对P34赋值
AUXR &= ~(0x10); //定时器2停止计时
定义变量时候最好初始化 定义初值 特别是用于指针Index 或者返回值
注意引脚的选取,锁存器P27,P26,P25
控制数码管,Led,继电器,蜂鸣器 P0引脚
注意运算和判断的先后顺序
记得定时器中断
eg. 定时器0 interrupt 1
定时器 1 interrupt 3
定时器 2 interrupt 12
串口 定时器2 interrupt 4
定时器0 ET0 = 1
定时器1 ET1 = 1
串口 ES = 1
因为不写会导致找不到中断入口从而程序卡死
记得把系统初始化函数,定时器函数放在mian中
其他程序记得放入main的while循环中
eg. '1'=49 '2'=50
eg. 'A'=65 'a'=97
会影响中断速度和运算
无符号型数据(unsigned int)与含负数型数据(int)判断大小时会认为负数为65536-绝对值 与准确常数比不会出现
增加条件 >0
在使用if else if 时可以注意前后逻辑进行排序优化
eg. if(A<0)Da_Write(0);else if(A<=500)Da_Write(51);else if(A 一层一层写
DA转化(有延时的函数eg.温度转化,EEPROM... )放在有延时轮询的函数里不要总是读取否则会影响其他程序 读取数值用变量
有时候不可避免用到float 类型计算
要注意接收变量的类型
在运算过程中不能有超过八个0左右 不要太大在过程中否则会乱给数据
可以先烧入到板子上看看
可以交换运算位置来近似
本来是500-2000的范围
在判断大小来决定模式时可以设置一个标志位不用重复判断逻辑符
比如反馈只在那个有延时函数的里面
不要在有延时的函数工程中放大量运算和需要及时反馈的运算结果
注意c程序中的函数和h文件中的函数名是否一样 类型是否一样 否则会导致数据无法读取函数无法使用
P2=P2&0x1f|0xc0;
RB2=Ad_Read(0x41); //读取上一个数据 所以人为调换顺序 强制类型转化
LDR=Ad_Read(0x43); //中间变量储存数据
RB2_Dat=RB2/51.0;
LDR_Dat=LDR/51.0;
RB2=Ad_Read(0x43);
RB2=Ad_Read(0x43);
LDR=Ad_Read(0x41);
LDR=Ad_Read(0x41);
如果Collect_Times++在末尾那么那个判断语句要注意更改
在AD转化时进行运算和判断大小时要先读取值后再进行判断否则会导致判断大小错误
可以先赋值P0口 再打开P2的锁存器
如果显示的数据有问题可能是变量类型范围不够 更换变量类型
运算过程中也要注意
float类型转化为整数型要注意转化类型的范围否则溢出会导致数据异常
比如一直显示某个值
如果时间读取放在AD前面会导致滑动变阻器的数据较小时异常跳动
可以将时间读取放在后面而且把滑动变阻器读取放在光敏前面
Led不正常闪烁可能是因为某个地方的if else 导致的Led开与灭
注意要记得将其他界面的小数点要合理的去除
如果按键没有用记得看按键函数里面引脚和赋值有没有问题
Led都不亮 看函数有没有放在主函数里 如果是优化的程序 看看Led_Disp();有没有使用
记得调整下载频率
芯片型号 STC15F2K60S2系列 ---IAP15F2K61S2
跳线帽记得选IO模式
蜂鸣器和继电器注意跳线帽是否接ON
#ifndef __ _H__
#define __ _H__
#endif
void System_Init()
{
P0=0xff;
P2=P2&0x1f|0x80; //Led初始化
P2&=0x1f;
P0=0x00; //为0因为有反相器所以输出1
P2=P2&0x1f|0xa0; //蜂鸣器继电器初始化
P2&=0x1f;
P0=0x00;
P2=P2&0x1f|0xc0; //Com断初始化
P2&=0x1f;
P0=0xff;
P2=P2&0x1f|0xe0; //段选初始化
P2&=0x1f;
}
void System_Init()
{
P2=P2&0x1f|0x80; //Led初始化
P0=0xff;
P2=P2&0x1f|0xa0; //蜂鸣器继电器初始化
P0=0x00; //为0因为有反相器所以输出1
P2&=0x1f;
}
void System_Init()
{
unsigned char temp=0;
P0=0xff;
temp=P2&0x1f;
temp=temp|0x80;
P2=temp;
temp=P2&0x1f;
P2&=temp;
P0=0x00;
temp=P2&0x1f;
temp=temp|0xa0;
P2=temp;
temp=P2&0x1f;
P2&=temp;
}
用temp直接运算最后一次性赋值给P2
unsigned char Key()
{
unsigned char temp=0; //记得返回值初始化
P44=0,P42=1,P35=1; //最好不要赋值给P34
if(P33==0)temp=4;
if(P32==0)temp=5;
if(P31==0)temp=6;
if(P30==0)temp=7;
P44=1,P42=0,P35=1;
if(P33==0)temp=8;
if(P32==0)temp=9;
// if(P33==0&P32==0)temp=89; 双按 用Key_Old判断
if(P31==0)temp=10;
if(P30==0)temp=11;
P44=1,P42=1,P35=0;
if(P33==0)temp=12;
if(P32==0)temp=13;
if(P31==0)temp=14;
if(P30==0)temp=15;
return temp;
}
void Key_Proc()
{
static unsigned char Key_Val,Key_Down,Key_Old,Key_Up;
if(Key_Proc_Slow)return; //延时10ms左右消抖
Key_Proc_Slow=1;
Key_Val=Key(); //按键读取
Key_Down=Key_Val&(Key_Val^Key_Old); //捕捉下降沿
Key_Up=~Key_Val&(Key_Val^Key_Old); //捕捉上升沿
Key_Old=Key_Val; //辅助扫描
}
中断:if(++Key_Proc_Slow==10)Key_Proc_Slow=0;
void Key_Proc()
{
static unsigned char Key_Val,Key_Down,Key_Old,Key_Up;
if(Key_Proc_Slow<10)return; //延时10ms左右消抖
Key_Proc_Slow=0;
Key_Val=Key(); //按键读取
Key_Down=Key_Val&(Key_Val^Key_Old); //捕捉下降沿
Key_Up=~Key_Val&(Key_Val^Key_Old); //捕捉上升沿
Key_Old=Key_Val; //辅助扫描
}
中断:++Key_Proc_Slow;
对于4T强时间的应对
如果用串口
AUXR&=∽(0x10)
....
P3=0Xff 复位
AUXR|=0x10
因为串口要用P30和P31
void Led_Disp(unsigned char addr,enable) //两个入口参数 一个地址 一个使能位
{
static unsigned char temp = 0x00;
static unsigned char temp_old=0xff;
if(enable) //判断是否使能
temp |=0x01< else
temp &=~(0x01< if(temp!=temp_old) //改变一次数据只扫描一次
{
P0=~temp; //取反 使得1为Led使能 先将P0赋值
P2=P2&0x1f|0x80; //锁存器开门
P2&=0x1f;
temp_old=temp;
}
}
unsigned char UcLed[8]={0,0,0,0,0,0,0,0}; //定义储存变量
void Led_Proc()
{
}
中断里
static unsigned char Led_Pos=0;
if(++Led_Pos==8)Led_Pos=0; //类似数码管扫描函数
Led_Disp(Led_Pos,UcLed[Led_Pos]);
可以直接用Led_Disp(0,0)如果Led要求简单
但是要注意一定是P0口先赋值
static unsigned char temp_1 = 0x00;
static unsigned char temp_old_1=0xff;
void Led_Disp(unsigned char*ucLed) //两个入口参数 一个地址 一个使能位
{
temp_1=0x00;
temp_1=(ucLed[0]<<0)|(ucLed[1]<<1)|(ucLed[2]<<2)|(ucLed[3]<<3)|(ucLed[4]<<4)|(ucLed[5]<<5)|(ucLed[6]<<6)|(ucLed[7]<<7);
if(temp_1!=temp_old_1) //改变一次数据只扫描一次
{
P0=~temp_1; //取反 使得1为Led使能 先将P0赋值
P2=P2&0x1f|0x80; //锁存器开门
P2&=0x1f;
temp_old_1=temp_1;
}
void Led_Off() //关闭所有Led
{
P0=0xff;
P2=P2&0x1f|0x80; //锁存器开门
P2&=0x1f;
temp_old_1=0x00;
}
unsigned char UcLed[8]={0,0,0,0,0,0,0,0}; //定义储存变量
void Led_Proc()
{
UcLed[0]=1;
UcLed[2]=1; //1为亮
....
Led_Disp(UcLed);
}
void Buzz_Disp(unsigned char enable) //类似Led 蜂鸣器函数
{
static unsigned char temp=0x00,temp_Old=0xff;
if(enable)
{
temp|=0x40;
}
else{temp&=~0x40;}
if(temp!=temp_Old)
{
P0=temp;
P2=P2&0x1f|0xa0;
P2&=0x1f;
temp_Old=temp;
}
}
void Relay_Disp(unsigned char enable) //类似Led 继电器函数
{
static unsigned char temp=0x00,temp_Old=0xff;
if(enable)
{
temp|=0x10;
}
else{temp&=~0x10;}
if(temp!=temp_Old)
{
P0=temp;
P2=P2&0x1f|0xa0;
P2&=0x1f;
temp_Old=temp;
}
}
需要同时用继电器和蜂鸣器要把temp拿出来公用写
unsigned char Location[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char Number[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
void Seg(unsigned char Loc,Num,Point) //数码管显示函数 3个入口参数 位选 段选 小数点 共阳极数码管
{
P0=0xff; //段选关闭---消影---为了避免鬼影现象
P2=P2&0x1f|0xe0;
P2&=0x1f;
P0=Location[Loc]; //位选
P2=P2&0x1f|0xc0;
P2&=0x1f;
P0=Number[Num]; //段选
if(Point!=0)P0&=0x7f; //小数点Point=1 打开小数点
P2=P2&0x1f|0xe0;
P2&=0x1f;
}
unsigned char Seg_Buf[8]={16,16,16,16,16,16,16,16}; //定义储存变量
unsigned int Seg_Proc_Slow=0;
void Seg_Proc()
{
if(Seg_Proc_Slow)return; //延时500ms左右
Seg_Proc_Slow=1;
}
中断
static unsigned char Seg_Pos=0;
if(++Seg_Proc_Slow==500)Seg_Proc_Slow=0;
if(++Seg_Pos==8)Seg_Pos=0; //扫描函数
Seg(Seg_Pos,Seg_Buf[Seg_Pos],0);
也可以
中断:
if(++Seg_Pos==8)Seg_Pos=0; //扫描函数
if(Seg_Buf[Seg_Pos]>20)
Seg(Seg_Pos,Seg_Buf[Seg_Pos]-',',1);
else
Seg(Seg_Pos,Seg_Buf[Seg_Pos],0);
所以要加小数点可以Seg_Buf[0]=1+',';
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //打开中断0
EA = 1; //运行中断
}
void Timer0Server() interrupt 1 //中断服务函数
{
}
底层ds1302
引入头文件 #include #include
定义引脚
sbit SCK=P1^7; //SCK
sbit SDA=P2^3; //IO输入输出口 注意3个引脚都是Ds1302的不要搞混
sbit RST=P1^3; //CE复位引脚
void Set_Rtc(unsigned char*ucRtc)
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00); //关闭保护位WP--0
Write_Ds1302_Byte(0x80,0x80); //停止时钟芯片
// Write_Ds1302_Byte(0x84,ucRtc[0]); 时 12进制 0x04
// Write_Ds1302_Byte(0x82,ucRtc[1]); 分
// Write_Ds1302_Byte(0x80,ucRtc[2]); 秒
for(i=0;i<3;i++)
Write_Ds1302_Byte(0x84-2*i,ucRtc[i]);
Write_Ds1302_Byte(0x8e,0x80); //开启保护位WP--1
}
void Read_Rtc(unsigned char*ucRtc)
{
unsigned char i;
// ucRtc[0]=Read_Ds1302_Byte(0x85); 时
// ucRtc[1]=Read_Ds1302_Byte(0x83); 分
// ucRtc[2]=Read_Ds1302_Byte(0x81); 秒
for(i=0;i<3;i++) // for 循环
ucRtc[i]=Read_Ds1302_Byte(0x85-2*i);
}
unsigned char ucRtc[]={0x23,0x59,0x55}; //0--时 1--分 2--秒 16进制数
信息处理函数
Read_Rtc(ucRtc); //读取数据
上电主函数
Set_Rtc(ucRtc); //写入数据
取数值时
十位 /16%16
各位 %16
底层 onewire
注意延时有循环12次
定义引脚
sbit DQ=P1^4;
float read_Temperature() //注意float类型返回变量
{
unsigned char high=0,low=0; //定义两变量
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; //高位左移8位或上地位除以16.0
}
按顺序往下读取
float TL;
信息处理函数
TL=read_Temperature();
Seg_Buf[0]= (unsigned char)TL/10%10; //记得强制类型转换
Seg_Buf[1]=(unsigned char)TL%10;
Point_Buf[1]=1;
Seg_Buf[2]=(unsigned int)(TL*10)%10;
Seg_Buf[3]=(unsigned int)(TL*100)%10; //记得相乘先打括号
Seg_Buf[4]=(unsigned int)(TL*1000)%10;
Seg_Buf[5]=(unsigned int)(TL*10000)%10;
unsigned int Tmp_Read()
{
unsigned char High=0,Low=0;
unsigned int temp=0;
init_ds18b20();
Write_DS18B20(0xcc); //跳过ROM
Write_DS18B20(0x44); //温度转化
init_ds18b20();
Write_DS18B20(0xcc); //跳过ROM
Write_DS18B20(0xbe); //读取指令
Low=Read_DS18B20(); //先读低位
High=Read_DS18B20(); //在读高位
temp=(High<<8)|Low;
temp=temp*25/4; //扩大100倍
return temp; //高位左移8位或上低位
}
小数可以用16进制编码可以不用float类型
PCF8591(光敏 滑动变阻 数字量和模拟量转化)
底层 iic
头文件 #include
定义引脚
sbit sda=P2^1;
sbit scl=P2^0;
unsigned char Ad_Read(unsigned char addr) //光敏电阻0x01 滑动变阻器0x03
{
unsigned char temp=0;
EA=0; //关闭中断防止中断打断
I2CStart(); //发送开始信号
I2CSendByte(0x90); // 写指令 地址位 --0x90
I2CWaitAck(); //等待应答
I2CSendByte(addr); //控制字 0x01光敏 0x03 滑动变阻
I2CWaitAck(); //等待应答
I2CStart(); //第二轮开始信号
I2CSendByte(0x91); // 读指令 地址位 --0x91
I2CWaitAck(); //等待应答
temp=I2CReceiveByte(); //将数据读出来 到temp中返回
I2CSendAck(1); //回答非应答 1 NO 告诉从机信号不读数据
I2CStop(); //停止
EA=1; //打开中断
return temp;
}
void Da_Write(unsigned char addr) //数字量转化为模拟量
{
I2CStart(); //启动
I2CSendByte(0x90); //写指令
I2CWaitAck(); //等待应答
I2CSendByte(0x40); //允许模拟量输出
I2CWaitAck(); //等待应答
I2CSendByte(addr); //写入数据
I2CWaitAck(); //等待应答
I2CStop(); //停止
}
unsigned char dat=0,dat2=0;
dat=Ad_Read(0x01); //Ad_Read 读取的值是上一次转换的结果 导致 Ad_Read(0x01)值被dat2读取
dat2=Ad_Read(0x03); //显示数据时注意认为改变顺序位置
所以光敏电阻的值在dat2中 滑动变阻器值在dat
其他处理函数
Da_Write(255); //数字量转化为模拟量
RB2=Ad_Read(0x03);
RB2=Ad_Read(0x03);
LDR=Ad_Read(0x01);
LDR=Ad_Read(0x01);
因为关闭了中断所以不能总是读取否则数码管会闪烁
AT24C02(EEPROM类似储存卡断电保存数据)
底层 iic
头文件 #include
定义引脚
sbit sda=P2^1;
sbit scl=P2^0;
// 写入EEPROM 函数 类似一个本子 写数组(char型)直接些数组名 写单变量+& eg. &a 地址(addr)最好是8的倍数 eg.0 8 16 一页最多八个字节 以8为一页
void EEPROM_Write(unsigned char *EEPROM_String,unsigned char addr,Num) //只能储存char类型 如果要int就利用char分开
{
I2CStart(); //发送开启信号
I2CSendByte(0xa0); //选择EEPROM芯片,确定写的模式
I2CWaitAck(); //等待EEPROM反馈
I2CSendByte(addr); //写入要储存的数据地址 //相当于页数
I2CWaitAck(); //等待应答
while(Num--) //循环位数
{
I2CSendByte(*EEPROM_String++); //将要写入的信息写入 数组指针 ++偏移一位
I2CWaitAck(); //等待应答
I2C_Delay(200); 延时200
}
I2CStop(); 停止发送
I2C_Delay(255);
I2C_Delay(255);
I2C_Delay(255);
I2C_Delay(255);
I2C_Delay(255);
I2C_Delay(255);
}
//读取EEPROM 函数
void EEPROM_Read(unsigned char *EEPROM_String,unsigned char addr,Num)
{
I2CStart(); //发送信号
I2CSendByte(0xa0); //选择EEPROM芯片,确定写的模式
I2CWaitAck(); //等待回应
I2CSendByte(addr); //选择要读取的数据地址
I2CWaitAck(); //等待回应
I2CStart(); //重新开始信号
I2CSendByte(0xa1); //选择EEPROM芯片,确定读的模式
I2CWaitAck(); //等待应答
while(Num--) //循环
{
*EEPROM_String++ =I2CReceiveByte(); //将要读的信息写入数组
if(Num)I2CSendAck(0); //发送应答 继续读数据
else I2CSendAck(1); //不应答 停止读数据
}
I2CStop(); //停止发送
}
unsigned char dat[]={40,60};
unsigned char A=100;
按键函数
switch (Key_Down)
{
case 4:
dat[0]+=10;
break;
case 5:
dat[0]-=10;
break;
case 6:
dat[1]+=10;
break;
case 7:
dat[1]-=10;
break;
case 8:
EEPROM_Write(dat,0,2); //将dat数据从第一页开始写入两个数据
break;
case 9:
A+=10;
break;
case 10:
A-=10;
break;
case 11:
EEPROM_Write(&A,8,1); //&单变量型 将A数据一位写在第二页
break;
}
主函数起始位置 上电读取一次 最好放在中断之前
EEPROM_Read(&A,8,1); //读取第二页一位数据给A
EEPROM_Read(dat,0,2); //读取第一页两位数据给dat
写入可以直接写 EEPROM_Write(&A,0,2);
读要分开读取EEPROM_Read(&high,0,1); EEPROM_Read(&low,1,1);
拼装 A=high<<8|low;
字节数
#include /*如果数据一直在2-5或者卡在3左右徘徊检查超声波跳线帽是否按紧*/
#include
sbit Tx=P1^0; //定义两引脚
sbit Rx=P1^1;
void Delay12us(void) //@12.000MHz 延时12us函数
{
unsigned char data i;
_nop_();
_nop_();
i = 33;
while (--i);
}
void Wave_Init() //超声波初始化函数 产生8个40kHz的方波信号 一个周期大约25us 两个12us延时
{
unsigned char i=0; 定义循环变量
for(i=0;i<8;i++)
{
Tx=1;
Delay12us();
Tx=0;
Delay12us();
}
}
unsigned char Ut_Wave_Read() //超声波距离读取函数
{
unsigned int time=0; //时间存储变量 16位 int型
TMOD &=0x0f; //配置定时器1模式
TH1 =TL1 =0; //复位计数值 等待超声波信号发出
Wave_Init(); //发送超声波信号
TR1=1; //开始计时
while((Rx==1)&&(TF1==0));//等待接受返回值信号或者定时器溢出 溢出 TF1=1
TR1=0;//停止计时
if(TF1==0)
{
time = TH1<<8|TL1;//读取当前时间
return (time*0.017);//返回距离值 cm time *340/2 *10负4次方 因为 m--cm 100 s--us 1000000
}
else
{
TF1=0;//清除溢出标志位
return 0;
}
}
unsigned char Ultrasound=0; //扫描信息变量
unsigned char Ultrasound_Recv=0; //接收信息变量
信息处理函数
Ultrasound=Ut_Wave_Read();
if((0<=Ultrasound-Ultrasound_Recv<10)||(0<=Ultrasound_Recv-Ultrasound<10))//检测是否相差小于10 是 赋值 防止跳动相差过大
{
Ultrasound_Recv=Ultrasound;
}
Seg_Buf[0]=Ultrasound_Recv/100%10;
Seg_Buf[1]=Ultrasound_Recv/10%10; //显示接收信息
Seg_Buf[2]=Ultrasound_Recv%10;
#include
#include
sbit Tx=P1^0;
sbit Rx=P1^1;
void Delay12us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 33;
while (--i);
}
void Wave_Init() //超声波初始化 产生8个 40KHZ的方波 近似 25us 一个周期
{
unsigned char i=0;
for (i=0;i<8;i++)
{
Tx=1;
Delay12us();
Tx=0;
Delay12us();
}
}
unsigned int Ut_Wave_Read()
{
unsigned int time=0; //时间存储变量 16位 int型
CH=CL=0; //清空PCA寄存器计数值
CCON =0x00; //初始化PCA控制寄存器/PCA定时器停止/清除CF
EA=0;
Wave_Init();
CR = 1; //PCA开始计数
EA=1;
while(Rx&&!CF); //等待接受返回值信号 或者定时器溢出 因为溢出 CF1=1 接收到返回值 Rx=0;
CR = 0; //接受到信号或者计时器溢出 停止计时
if(CF==0) //计时器没有溢出 正常读数
{
time=(CH<<8)|CL;
return(time*0.017); //返回距离值 cm time/2 *340 *10负4次方 m - cm 100 s-us -1000000
}
else
{
CF=0; //清除溢出标志位
return 0;
}
}
原本的定时器T改为C就可以
#include
void Uart1_Init(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xE6; //设置定时初始值
T2H = 0xFF; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES=1; //允许串行口中断
EA=1; //开放中断
}
//重定向
extern char putchar (char ch) //#include 里面的函数
{
SBUF = ch;
while (TI==0);
TI = 0;
return(ch);
}
#include //%d... printf() 标准输入输出头文件库
#include //清除上次接收数据头文件 memset
unsigned char Uart_Recv[10]; //串口接收数据储存数组 默认10个字节
unsigned char Uart_Recv_Index=0; //串口接收数组指针
unsigned int Uart_Proc_Slow=0;
unsigned char dat; //储存数据变量
float T; //eg.温度变量
按键处理函数
void Key_Proc()
{
static unsigned char Key_Val,Key_Down,Key_Old;
if(Key_Proc_Slow)Key_Proc_Slow=0;
Key_Proc_Slow=1;
Key_Val=Key();
Key_Down=Key_Val&(Key_Val^Key_Old);
Key_Old=Key_Val;
if(Key_Down==4)
{
printf("温度=%.2f\r\n",T);
}
}
信息处理函数
T=read_Temperature();
Seg_Buf[0]=dat/10%10;
Seg_Buf[1]=dat%10;
void Uart_Proc() //串口处理函数
{
if(Uart_Recv_Index==0)return;
if(Uart_Tick>=10)
{
Uart_Tick=Uart_Flag=0; //计时复位
if(Uart_Recv_Index==1)
{
dat = Uart_Recv[0] - 48; //ASCII 码值 '1'字符 49 '2'字符 50 相差48 'a'97 'A'65 相差32
}
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;
}
}
memset(Uart_Recv,0,Uart_Recv_Index); //清除上次接收数据
Uart_Recv_Index=0; //指针复位
}
}
1ms中断服务
if(Uart_Flag)Uart_Tick++;
void Uart1Server() interrupt 4
{
if(RI==1) //串口接受数据 {
Uart_Recv[Uart_Recv_Index]=SBUF;
Uart_Recv_Index++;
RI=0;
Uart_Flag=1;
Uart_Tick=0;
}
if(Uart_Recv_Index > 6)Uart_Recv_Index=0; // >i 这个数据根据需要发送的数据占位 而复位
}
%d -- int 整数类型
%c -- char 字符串
%u--unsingend 无符号类型
\r\n 换行符
如果接收串口有乱码闪烁问题可能是没有在主函数中使用Uart_Proc()
或者在此函数中没有
memset(Uart_Recv,0,Uart_Recv_Index); //清除上次接收到的数据
Uart_Recv_Index=0; //指针复位
在使用串口时 就算是只用发送也需要写入中断函数 但是可以不写内容
没有中断就会卡程序
定时器1用来延时
不要开定时器0的中断
16位不重装载
初始值TL0=0x00;TH0=0x00;
TMOD |=0x05 计数模式
void Timer0_Init(void) //1毫秒@12.000MHz 16 位不重装载
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置计数器模式
TL0 = 0x00; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时 //不要开中断
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 =1;
EA =1;
}
void Timer1_Sever() interrupt 3
{
if(++Timer1s==1000)
{
Count_Flag=1; //测量后标志拉高 为了读取有效值
Timer1s=0;
Count= TH0<<8|TL0; //取出计数值
TH0=TL0=0; //手动重装载
}
}
在主函数里面
Timer0_Init(); //先初始化定时器0
Timer1_Init();
准考证打印出来和身份证
比赛时间5个小时带点吃的
带上笔和草稿纸
15道客观题 1道主观题
有问题就和监考老师说
而且添加在User中
安装在Keil5文件夹中
有问题可以在单片机指南中看 ISP调试指南
进入考点,按照要求打开机器
新建工程要放在没有被保护的硬盘比如D盘 或者老师要求
为了防止卡机重启数据丢失
比如点个灯
STC下载助手一定要从官方文件夹中打开
测试完毕后,新建文件夹与工程(注意命名 一般是学号)
选择题会就会不要太纠结
工程先实现数码管显示等,可以边写边调试 观察是否符合要求
覆盖性的提交防止最后网卡
记得保存
zip压缩文件
注意正确率
省赛题至少刷一遍
最好再刷国赛 降维打击
小蜜蜂笔记wx公众号
芯片相关可以查手册
前一两周学习
自由主题