学过51单片机的回过头来都会觉得51还是比较简单的,在此我将贴出在我的学习过程中,把对各种外设所进行的操作,封装成函数库的形式,以供新手学习。
注:使用的单片机是stc12c5a60s2,该系列单片机属于加强51,在运行速度上是普通51的8-12倍,有关时序的操作需要加以注意。
注2:使用示例:
void main()
{
char i;
char array[14] = "lalalal";
lcd_init();
delayms(1000); //等待DHT11稳定
while(1)
{
i = GetData(); //读数据
if(i != 0) //有错误
{
break; //重新开始
}
i = Check(); //数据校验
if(i != 0) //有错误
{
break; //重新开始
}
//此处应该得到准确数据;
i = sprintf(array, "HR:%d.%d", (int)dat_r[0], (int)dat_r[1]);//湿度数值字符串放入array
array[i] = '\0';
lcd_pos(0, 0); //第0行显示
i = 0;
while('\0' != array[i])
lcd_wdat(array[i++]);
i = sprintf(array, "TEMP:%d.%d", (int)dat_r[2], (int)dat_r[3]);
array[i] = '\0';
lcd_pos(1, 0);
i = 0;
while('\0' != array[i])
lcd_wdat(array[i++]);
// dat_r[0]; //湿度整数
// dat_r[1]; //湿度小数(根据数据手册,DHT11小数部分一直是0没用)
// dat_r[2]; //温度整数
// dat_r[3]; //温度小数(根据数据手册,DHT11小数部分一直是0没用)
// dat_r[4]; //校验值
delayms(1000); //经测试,两次连读要至少延时80ms
}
}//main
申明:本系列全部例程通过单片机开发板,实验亲测有效!
/* dht11 */
#define JUDGE 30 //用于判断通信的0和1,与单片机速度和晶振频率有关
sbit DATA = P1^0; //定义数据引脚
uchar dat_r[5]; //用于存放从DHT11读取到的数值
/*****************************************************************************
函数名:DHT11读数据函数
调 用:? = GetData();
参 数:无
返回值:失败->-1,-2,-3,-4;成功->0
结 果:读DHT11数据并保存到数组dat_r[]
备 注:
******************************************************************************/
char GetData (void)
{
uchar i,j; //for循环变量
uchar t; //超时判断
uchar dat8=0; //一次读取的8位数据,需要读5次
DATA = 0; //主机发起始信号
delayms(20); //主机拉低总线至少18ms
DATA = 1; //主机拉高总线20~40us
delay10us(3);
t = 80; //设置超时等待时间
while(DATA && t--); //等待DHT11拉低总线
if(t == 0) //超时
{
DATA = 1;
return -1; //通信错误退出,返回错误信号:-1
}
//等80us响应信号
t = 250; //设置超时等待时间
while(!DATA && t--); //等待DHT11拉高总线
if(t == 0) //超时
{
DATA = 1;
return -2; //通信错误退出,返回错误信号:-2
}
//等80us响应信号
t = 250; //设置超时等待时间
while(DATA && t--); //等待DHT11拉低总线
if(t == 0) //超时
{
DATA = 1;
return -3; //通信错误退出,返回错误信号:-3
}
for(j=0; j<5; j++) //5次读取
{
for(i=0; i<8; i++) //1次8个位
{
//等待50us开始时隙
t = 150; //设置超时等待时间
while(!DATA && t--); //等待DHT11拉高总线
if(t == 0) //超时
{
DATA = 1;
return -4; //通信错误退出,返回错误信号:-4
}
t = 0; //记录时间清零
while(DATA && ++t); //等待并记录高电平持续时间
dat8 <<= 1;
if(t > JUDGE) //高电平持续时间较长(70us)
dat8 += 1; //传输值为1
//else dat8 += 0;
}
dat_r[j] = dat8;
}
delay10us(3); //等待DHT11拉低50us
delay10us(3);
DATA = 1; //结束,拉高总线
return 0; //返回成功信号
}
/******************************************************************************
函数名:数据校验函数
调 用:? = Check();
参 数:无
返回值:成功->0;失败->-1;
结 果:数据校验
备 注:数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
******************************************************************************/
char Check (void)
{
uchar i; //for循环变量
uint chk=0; //校验和
for(i=0; i<4; i++)
chk += dat_r[i]; //累加
if((uchar)chk != dat_r[4]) //比对
return -1; //返回错误信号:-1
else
return 0; //返回正确信号:0
}