关于电子钟:
Ds1302:
自写->Ds1302_Single_Byte_Write(0x8e, 0x00);
Ds1302_Single_Byte_Write(0x84, shi/10*16+shi%10);
Ds1302_Single_Byte_Write(0x82, fen/10*16+fen%10);
Ds1302_Single_Byte_Write(0x80, miao/10*16+miao%10);
Ds1302_Single_Byte_Write(0x8e, 0x80);
将BCD码转换成二进制:hour/16*10+hour%16
将二进制转换成BCD码:shi/10*16+shi%10
读取温度:
temp=Read_temp(); //读温度
读时间: hour=Ds1302_Single_Byte_Read(0x85); //读时间
min=Ds1302_Single_Byte_Read(0x83);
sec=Ds1302_Single_Byte_Read(0x81);
关于风扇:
在于加上一个单独的显示函数
在switch-case语句中对于default的使用 , 如果是个循环,那么不用default
在定时器中断中我们的定时时间为100us , flag == 1000 , 数据过大可能出现错误 ,
因此在服务函数中用static静态变量防止数据出错
Read_temp ;
先初始化 , 写0xcc , 写0x44 , 延时200 , 初始化 , 写0xcc , 写0xbe , 读数据 , temp = TH<<4 | TL>> 4
关于温度记录器(Ds18b20 , ds1302, 数码管)
写ds1302初始化函数
将时间BCD码转换为数码管读取的数 hour/16 hour%16
注意变量初识化!!!!!!!
关于EEPROM:
写数据进去:
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(date);
IIC_WaitAck();
IIC_Stop();
Delay10ms();
读数据:
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_Stop();
Delay10ms();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
date = IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return date
读取PCF8591的AD值:
unsigned char ad;
IIC_Start();
IIC_SendByte(0x90);//PCF8951的地址
IIC_WaitAck();
IIC_SendByte(chanel);
IIC_WaitAck();
IIC_Stop();
Delay10ms();//写地址结束后需要延时10ms?
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
ad=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return ad;
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
SDA_R=0;//!!!!!!!!添上去
return dat;
调试时一直无法显示分钟的值导致浪费一大堆时间:
检查后发现原来例程中第一次调用Read_Ds1302_Byte后 , 没有将SDA_R 清零!!!!!!
}
关于写进AT24C02中的数据:
Write_AT24C02(0x00,set_shidu);为什么是0x00的地址?? 因为是写的第一个地址
采用调用函数的方法看着更舒服
间隔50ms 显示很舒服,哈哈哈.
哈哈哈 , 终于知道怎么计算AD数模转换的值了;
*adNum一定是0到255之间的一个数,因为pcf8591是8位的AD/DA芯片,所以输出的范围为00000000到11111111,即0到255*/
adNum=Pcf8591ReadByte(); //读出数值
/*将adNum转换成电压值,单片机的电压为5V,则电位器的电压为0到5V,用0到255表示0到5V,则每一个1代表5/255V,即0.01953V*/
关于售水机:
这次在Timer0中用了static , 出现错误.....
关于小数点的处理暂时没有找到好的办法 , 只有在有小数点时候重新写一个数组...
用if(!flag)还比较好用..
关于温度监控器:
从Ds18b20读温度
uchar Get_temp(void)
{
uchar temp;
Init_DS18B20();
0xcc , 0x40
Init_DS18B20();0xcc , 0xbe , TL = Read_DS18B20();TH = Read_DS18B20();temp = (TH << 4) | (TL >> 4)
注意写入顺序 , 以及高位左移4位 , 低位右移4位;
}
关于简易温度监控和控制系统(其实就是矩阵键盘而已 , 其他简单)
矩阵键盘的key_scan()
首先要给key初值 , key=15 , 具体思路是先接通一列的键盘 , 在识别行的键盘具体是哪个
P3 = 0x7f;
P42 = 1; // 还搞不清楚为什么需要控制P4口 / P36->P42 P37->P44 , 保证RD/WR的功能;
P44 = 0;
GPIO = P3;
GPIO &= 0x0f;
if (GPIO != 0x0f)
{
Delay10ms();
GPIO = P3;
GPIO &= 0x0f;
if (GPIO != 0x0f)
{
GPIO=P3;//!!注意这里需要重新赋给GPIO值
switch(GPIO)
{
case 0x7e:
key = 0;break;
case 0x7d:
key = 3;break;
case 0x7b:
key = 6;break;
case 0x77:
key = 9;break;
default:break;
}
}
while (GPIO != 0x0f)//while的位置在第一个if后面
{
GPIO = P3;
GPIO &= 0x0f;
}
}
还有就是对于flag的逻辑 , 何时开启/关闭那个flag , 用!flag还是flag...
C语言中,全局变量和局部静态变量是存储在静态存储区的,他们在分配的时候都被系统默认初始化为0;
而局部自动变量是在栈上分配内存的,如果不对它们进行初始化,那么他们可能是任意的随机值。
值得注意的是当我输入温度max<min时需要改正错误或者需要熄灭某些数码管是
for ( i = 0; i < 8; i++)
{
DisplayDate[i] = 10;
}
关于超声波:
先写一个SendWave();
{Trig = 0;
Delay20us();
Trig = 1;
Delay20us();}//产生方波
然后用一个定时器1;
uchar GetDistance(void)
{
uint distance;
Echo = 1;//接收端
TR1 = 1;//开启定时器1
SendWave();//发生方波
while ((Echo == 1) && (TF1 == 0));//当未接受并且定时器没有溢出65536???
TR1 = 0;
if (TF1 == 1)
{
TF1 = 0;//如果溢出了表明太远了吧
distance = 99;
}
else
{
distance = (TH1 << 8) | (TL >> 8);//16位的定时器,合成一个16位数据
distance *= 0.017;//time*340m/s / 2 = distance; = 换算毫米单位
}
TH1 = TL1 = 0;恢复初始值
return distance;
}
各个外设端口:蜂鸣器->0x40 继电器——>0x10 Led->P0
电位器RB2 chanel为3
0.8秒为间隔表示亮0.8秒