gaoyang9992006 发表于 2020-2-16 12:50

“玩板”+再次把玩人生中的第一块开发板

<div class='showpostmsg'> 本帖最后由 gaoyang9992006 于 2020-2-16 12:59 编辑

<p>&nbsp; &nbsp; &nbsp; &nbsp;说起这块板子,已经是十年前的事情, 十年前我刚到哈尔滨上学,在电子大世界买了一块开发板51开发板。从此开始了我的单片机学习之路。毕业后的若干年,他一直躺在我家的一个箱子里,近期由于病毒原因,导致只能憋在家里,最近天气突变,就想要不做个温湿度计,用于测量卧室内的温湿度,以便知道是不是该开空调了,或者该关空调了。</p>

<p>把开发板找到,还找到了一块LCD1602,经过测试,1602已经只剩下右边一小半可以显示了,估计老化严重了。还找到一个AM2301温湿度传感器。非常完美,可以工作了。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p></p>

<p>这就是我那块开发板,当时花了12元。只有最小系统。我还以为我买到便宜了呢。。。</p>

<p>&nbsp;</p>

<p></p>

<p>这是ISP编程器,用于烧录AT89S52的单片机。当时花了45元,其实贵了,老板还问我去其他家打听过价格没,我说没有。。</p>

<p>然后就给了我这个价格。</p>

<p>&nbsp;</p>

<p></p>

<p>这个是后来在二手市场淘的,忘了是多少钱了。</p>

<p></p>

<p>这是室内的自然温湿度,还是比较干燥的,北方嘛,昨天下雨了,今天打晴天,比较冷。早晨外面还结冰了。</p>

<p>用手捂住看看能否有变化</p>

<p></p>

<p>变化明显,因为有个外壳,所以升温比较慢,更容易测环境温度,不会受局部温度影响太大。</p>

<p><br />
接下来就是分享源码和工程了。非常有参考意义。因为我是分头文件编写的。可以直接拿走使用,移植到其他51工程里非常容易。</p>

<p><br />
<br />
<b><font color="#5E7384">此内容由EEWORLD论坛网友<font size="3">gaoyang9992006</font>原创,如需转载或用于商业用途需征得作者同意并注明出处</font></b></p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

gaoyang9992006 发表于 2020-2-16 13:02

<p>LCD1602.C 是主要文件,main函数也在这个里面了。方便LCD1602测试,也可以直接剪切到另外一个文件。&nbsp;</p>

<pre>
<code class="language-cpp">#include"LCD1602.h"
#include"AM2301.h"
void delay(unsigned int j)
{
       for(; j&gt;0; j--);
}

void LCD1602CheckBusy(void)
{
        unsigned char tem;
        LCD1602_RS_Low();
        LCD1602_RW_High();
        LCD1602_EN_Low();
        while(1)       
        {
                LCD1602_DATA_BUS=0xFF;
                LCD1602_EN_High();
//                tem=LCD1602_DATA_BUS;
                LCD1602_READ_DATA(tem,LCD1602_DATA_BUS);
                LCD1602_EN_Low();
                if((tem&amp;0x80)==0) break;               
        }
}

void LCD1602WriteCom(unsigned char com)
{
        LCD1602CheckBusy();
        LCD1602_RS_Low();
        LCD1602_RW_Low();
        LCD1602_EN_Low();
//        LCD1602_DATA_BUS=com;
        LCD1602_READ_DATA(LCD1602_DATA_BUS,com);
        delay(2);
        LCD1602_EN_High();
        delay(2);
        LCD1602_EN_Low();
}

void LCD1602WriteData(unsigned char dat)
{
        LCD1602CheckBusy();
        LCD1602_RS_High();
        LCD1602_RW_Low();
        LCD1602_EN_Low();       
//        LCD1602_DATA_BUS=dat;
        LCD1602_READ_DATA(LCD1602_DATA_BUS,dat);
        delay(2);
        LCD1602_EN_High();
        delay(2);
        LCD1602_EN_Low();
}

void LCD1602Init(void)
{
        LCD1602_EN_Low();
        LCD1602WriteCom(0x38);
        LCD1602WriteCom(0x0c);
        LCD1602WriteCom(0x06);
        LCD1602WriteCom(0x01);
        LCD1602WriteCom(0x80);
}
/*
void LCD1602DispString(unsigned char addr,unsigned char *str)
{
        unsigned char i=0;
        LCD1602WriteCom(addr);
        while(*str&gt;0)
        {
                LCD1602WriteData(*str++);
                delay(10);
        }
}
*/
/*写1位数字到指定的位置。参数:位置,1位字符*/
void LCD1602Disp1(unsigned char addr,unsigned char num)
{
        LCD1602WriteCom(addr);
        LCD1602WriteData(num);
        delay(2);//延时13+11*2 us,35us.
}

void main(void)
{
        unsigned int shidu,wendu;

        LCD1602Init();


        {

//                LCD1602DispString(0x80,"ABCDEFGHIJKLMNO");
//                LCD1602DispString(0xC0,"123456789012345");
//                LCD1602Disp1(0x8F,'0'+3);
//                LCD1602Disp1(0xCF,':');               
        }               
        while(1)
        {
                Read_Sensor();                  // 读取传感器数据
                shidu=Sensor_Data;
                shidu&lt;&lt;=8;
                shidu=shidu|Sensor_Data;
                wendu=Sensor_Data;
                wendu&lt;&lt;=8;
                wendu=wendu|Sensor_Data;
                LCD1602Disp1(0x8B,'0'+shidu/100);       
                LCD1602Disp1(0x8C,'0'+shidu%100/10);
                LCD1602Disp1(0x8D,'.');               
                LCD1602Disp1(0x8E,'0'+shidu%100%10);
                LCD1602Disp1(0x8F,'%');
                if(wendu&amp;0x8000)
                {
                        LCD1602Disp1(0xCA,'-');
                        wendu=wendu&amp;0x7FFF;
                }
                else
                LCD1602Disp1(0xCA,'+');
               
                LCD1602Disp1(0xCB,'0'+wendu/100);       
                LCD1602Disp1(0xCC,'0'+wendu%100/10);
                LCD1602Disp1(0xCD,'.');                       
                LCD1602Disp1(0xCE,'0'+wendu%100%10);
                LCD1602Disp1(0xCF,'C');                       
        }

}</code></pre>

<p>&nbsp;</p>

gaoyang9992006 发表于 2020-2-16 13:03

<p>这个是LCD1602.h文件,定义了管教的分配,只要修改这个文件就可以在51工程里轻松移植到其他管脚去。&nbsp;</p>

<pre>
<code class="language-cpp">#include &lt;AT89X52.h&gt;
#include&lt;intrins.h&gt;//包含_nop_()函数定义的头文件
#define LCD1602_DATA_BUS P0

sbit LCD1602_RS=P2^0;
sbit LCD1602_RW=P2^1;
sbit LCD1602_EN=P2^2;
#define LCD1602_RS_High() LCD1602_RS=1
#define LCD1602_RS_Low()LCD1602_RS=0
#define LCD1602_RW_High() LCD1602_RW=1
#define LCD1602_RW_Low()LCD1602_RW=0
#define LCD1602_EN_High() LCD1602_EN=1
#define LCD1602_EN_Low()LCD1602_EN=0
/*从b里读数据写到a.                例如:tem=LCD1602_DATA_BUS;可以写作LCD1602_READ_DATA(tem,LCD1602_DATA_BUS);*/
#define LCD1602_READ_DATA(a_addr,b_addr) a_addr=b_addr


/*延时函数,延时时间=13+11*j,例如当j=17时,延时为200us*/
void delay(unsigned int j);
/*写指令函数。参数:指令*/
void LCD1602WriteCom(unsigned char com);
/*写数据函数。参数:写入数据*/
void LCD1602WriteData(unsigned char dat);
/*初始化函数。参数:无*/
void LCD1602Init(void);
/*检查忙指令。参数:无*/
void LCD1602CheckBusy(void);
/*写字符串。参数:地址(第一行0x80~0x8F,第二行0xC0~0xCF),字符串*/
void LCD1602DispString(unsigned char addr,unsigned char *str);
/*写1位数字到指定的位置。参数:位置,1位字符*/
void LCD1602Disp1(unsigned char addr,unsigned char num);</code></pre>

<p>&nbsp;</p>

gaoyang9992006 发表于 2020-2-16 13:05

<p>这个是AM2301.h</p>

<p>定义了端口和存储温湿度的数组,只要包含这个文件,并调用读取函数就行了,然后从数组了读取转换结果用于显示。&nbsp;</p>

<pre>
<code class="language-cpp">//AM2301
#include &lt;AT89X52.h&gt;
#include&lt;intrins.h&gt;//包含_nop_()函数定义的头文件
//读传感器 端口位定义,可修改
sbit AM2301_PIN = P2^3;

// 变量定义
unsigned char Sensor_Data={0x00,0x00,0x00,0x00,0x00};
unsigned char Sensor_Check;                  //校验和

unsigned char Sensor_AnswerFlag;//收到起始标志位
unsigned char Sensor_ErrorFlag;   //读取传感器错误标志
unsigned intSys_CNT;

/********************************************\
|* 功能: 延时        晶振为12M时                                  *|
|*t = 1 为 20us然后成倍增加10us左右                *|
\********************************************/
void Delay_N10us(unsigned char t)
{
    while(t--)
   {
          _nop_();
   }
}
/********************************************\
|* 功能: 延时        晶振为12M时                                        *|
|* 延时大约 1ms                                                          *|
\********************************************/
void Delay_N1ms(unsigned int t)
{
unsigned int i;
unsigned int j;
for(j=t;j&gt;0;j--)
   for(i=124;i&gt;0;i--);//延时大约 1ms
}

/********************************************\
|* 功能: 读传感器发送的单个字节                *|
\********************************************/
unsigned char Read_SensorData(void)
{
        unsigned char i,cnt;
        unsigned char buffer,tmp;
        buffer = 0;
        for(i=0;i&lt;8;i++)
        {
                cnt=0;
                while(!AM2301_PIN)        //检测上次低电平是否结束
                {
                  if(++cnt &gt;= 300)
                   {
                          break;
                   }
                }
                //延时Min=26us Max50us 跳过数据"0" 的高电平
                Delay_N10us(2);       //延时30us   
               
                //判断传感器发送数据位
                tmp =0;
                if(AM2301_PIN)       
                {
                  tmp = 1;
                }
                cnt =0;
                while(AM2301_PIN)                //等待高电平 结束
                {
                           if(++cnt &gt;= 200)
                        {
                          break;
                        }
                }
                buffer &lt;&lt;=1;
                buffer |= tmp;       
        }
        return buffer;
}

/********************************************\
|* 功能: 读传感器                            *|
\********************************************/
unsigned char Read_Sensor(void)
{
                unsigned char i;
                //主机拉低(Min=800US Max=20Ms)
    AM2301_PIN = 0;
                Delay_N1ms(2);//延时2Ms
                //释放总线 延时(Min=30us Max=50us)
                AM2301_PIN = 1;        
                Delay_N10us(1);//延时30us
                //主机设为输入 判断传感器响应信号
                AM2301_PIN = 1;
           Sensor_AnswerFlag = 0;// 传感器响应标志       
                //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行          
                if(AM2301_PIN ==0)
                {
                       Sensor_AnswerFlag = 1;//收到起始信号
                       Sys_CNT = 0;
                       //判断从机是否发出 80us 的低电平响应信号是否结束       
                       while((!AM2301_PIN))
                       {
                                       if(++Sys_CNT&gt;300) //防止进入死循环
                                        {
                                       Sensor_ErrorFlag = 1;
                                       return 0;
                                        }
                                }
                                Sys_CNT = 0;
                                //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
                                while((AM2301_PIN))
                                {
                                       if(++Sys_CNT&gt;300) //防止进入死循环
                               {
                                       Sensor_ErrorFlag = 1;
                                       return 0;
                               }
                                }                
                                // 数据接收        传感器共发送40位数据
                                // 即5个字节 高位先送5个字节分别为湿度高位 湿度低位 温度高位 温度低位 校验和
                                // 校验和为:湿度高位+湿度低位+温度高位+温度低位
                                for(i=0;i&lt;5;i++)
                                {
                                        Sensor_Data = Read_SensorData();
                                }
                        }
                        else
                        {
                                Sensor_AnswerFlag = 0;          // 未收到传感器响应       
                        }
          return 1;
} </code></pre>

<p>&nbsp;</p>

gaoyang9992006 发表于 2020-2-16 13:06

<p>等我再翻翻,如果找到个合适的显示器,或者无线模块,准备做个联网的,可以手机APP查看测量结果。</p>

chenbingjy 发表于 2020-2-16 15:11

<p>厉害</p>

led2015 发表于 2020-4-10 23:04

<p>厉害的,感觉动手能力蛮强的</p>
页: [1]
查看完整版本: “玩板”+再次把玩人生中的第一块开发板