找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2256|回复: 1
打印 上一主题 下一主题
收起左侧

LM75A温度计12864液晶显示程序 二手温控器改装之旅

[复制链接]
跳转到指定楼层
楼主
TB来的二手温控器,加装液晶屏之旅。

制作出来的实物图如下:


说明:


单片机源程序如下:

  1. #include <reg52.h>
  2. #include <INTRINS.H>
  3. #include <stdio.h>
  4. #include  <intrins.h>
  5. #define uchar unsigned char
  6. #define uint  unsigned int
  7. /* ***************************************************** */
  8. // 起别名定义
  9. /* ***************************************************** */
  10. typedef unsigned char uChar8;
  11. typedef unsigned int  uInt16;
  12. typedef enum{FALSE,TRUE} BOOL;
  13. /* ***************************************************** */
  14. // 宏定义
  15. /* ***************************************************** */
  16. #define LM75ADevIDAddr 0x90         
  17. #define IIC_WRITE 0x00
  18. #define IIC_READ  0x01
  19. /* ***************************************************** */
  20. // 位定义
  21. /* ***************************************************** */
  22. sbit SCL = P2^1;//
  23. sbit SDA = P2^0;
  24. long int LM75WD;



  25. /* ***************************************************** */
  26. // 全局变量定义
  27. /* ***************************************************** */
  28. bit p_bH0L_Flag;                                        // 温度"0"上、下标志位
  29. float p_fLM75ATemp;                                        // 温度值

  30. /* ***************************************************** */
  31. // 函数名称:Delay5US()
  32. // 函数功能:微秒延时
  33. // 入口参数:延时微秒数(ValUS)
  34. // 出口参数:无
  35. /* ***************************************************** */
  36. void Delay5US(void)
  37. {
  38.         _nop_();_nop_();_nop_();_nop_();
  39. }
  40. /* ***************************************************** */
  41. // 函数名称:DelayMS()
  42. // 函数功能:毫秒延时
  43. // 入口参数:延时毫秒数(ValMS)
  44. // 出口参数:无
  45. /* ***************************************************** */
  46. void DelayMS(uInt16 ValMS)
  47. {
  48.         uInt16 uiVal,ujVal;
  49.         for(uiVal = 0; uiVal < ValMS; uiVal++)
  50.                 for(ujVal = 0; ujVal < 120; ujVal++);
  51. }



  52. /* ***************************************************** */
  53. // 函数名称:IIC_Start()
  54. // 函数功能:IIC起动
  55. // 入口参数:无
  56. // 出口参数:无
  57. /* ***************************************************** */
  58. void IIC_Start(void)
  59. {
  60.         SDA = 1;
  61.         Delay5US();
  62.         SCL = 1;
  63.         Delay5US();
  64.         SDA = 0;
  65.         Delay5US();
  66. }
  67. /* ***************************************************** */
  68. // 函数名称:IIC_Stop()
  69. // 函数功能:IIC停止
  70. // 入口参数:无
  71. // 出口参数:无
  72. /* ***************************************************** */
  73. void IIC_Stop(void)                     
  74. {
  75.         SDA = 0;
  76.         Delay5US();
  77.         SCL = 1;
  78.         Delay5US();
  79.         SDA =1;
  80. }
  81. /* ***************************************************** */
  82. // 函数名称:IIC_Ack()
  83. // 函数功能:IIC应答
  84. // 入口参数:无
  85. // 出口参数:无
  86. /* ***************************************************** */
  87. void IIC_Ack(void)                     
  88. {
  89.         SCL = 0;                                // 为产生脉冲准备
  90.         SDA = 0;                                // 产生应答信号
  91.         Delay5US();                                // 延时你懂得
  92.         SCL = 1;Delay5US();  
  93.         SCL = 0;Delay5US();                // 产生高脉冲
  94.         SDA = 1;                                // 释放总线
  95. }
  96. /* ***************************************************** */
  97. // 函数名称:IIC_RdAck()
  98. // 函数功能:读IIC应答
  99. // 入口参数:无
  100. // 出口参数:是否应答真值
  101. /* ***************************************************** */
  102. BOOL IIC_RdAck(void)                     
  103. {
  104.         BOOL AckFlag;
  105.         uChar8 uiVal = 0;
  106.         SCL = 0;Delay5US();   
  107.         SDA = 1;
  108.         SCL = 1;Delay5US();
  109.         while((1 == SDA) && (uiVal < 255))
  110.         {
  111.                 uiVal ++;
  112.                 AckFlag = SDA;
  113.         }
  114.         SCL = 0;  
  115.         return AckFlag;                // 应答返回:0;不应答返回:1
  116. }
  117. /* ***************************************************** */
  118. // 函数名称:IIC_Nack()
  119. // 函数功能:IIC不应答
  120. // 入口参数:无
  121. // 出口参数:无
  122. /* ***************************************************** */
  123. void IIC_Nack(void)                    
  124. {   
  125.         SDA = 1;
  126.         SCL = 0;Delay5US();      
  127.         SCL = 1;Delay5US();      
  128.         SCL = 0;
  129. }
  130. /* ***************************************************** */
  131. // 函数名称:OutputOneByte()
  132. // 函数功能:从IIC器件中读出一个字节
  133. // 入口参数:无
  134. // 出口参数:读出的一个字节(uByteVal)
  135. /* ***************************************************** */
  136. uChar8 OutputOneByte(void)        
  137. {
  138.         uChar8 uByteVal = 0;
  139.         uChar8 iCount;
  140.         SDA = 1;
  141.         for (iCount = 0;iCount < 8;iCount++)
  142.         {
  143.                 SCL = 0;
  144.                 Delay5US();
  145.                 SCL = 1;
  146.                 Delay5US();
  147.                 uByteVal <<= 1;
  148.                 if(SDA)
  149.                         uByteVal |= 0x01;
  150.         }         
  151.         SCL = 0;
  152.         return(uByteVal);
  153. }
  154. /* ***************************************************** */
  155. // 函数名称:InputOneByte()
  156. // 函数功能:向IIC器件写入一个字节
  157. // 入口参数:待写入的一个字节(uByteVal)
  158. // 出口参数:无
  159. /* ***************************************************** */
  160. void InputOneByte(uChar8 uByteVal)
  161. {
  162.     uChar8 iCount;
  163.     for(iCount = 0;iCount < 8;iCount++)
  164.         {  
  165.                 SCL = 0;
  166.                 Delay5US();                        
  167.                 SDA = (uByteVal & 0x80) >> 7;
  168.                 Delay5US();         
  169.                 SCL = 1;
  170.                 Delay5US();
  171.                 uByteVal <<= 1;
  172.     }
  173.         SCL = 0;            
  174. }
  175. /* ***************************************************** */
  176. // 函数名称:IIC_WrDevAddAndDatAdd()
  177. // 函数功能:向IIC器件写入器件和数据地址
  178. // 入口参数:器件地址(uDevAdd),数据地址(uDatAdd)
  179. // 出口参数:写入是否成功真值
  180. /* ***************************************************** */
  181. BOOL IIC_WrDevAddAndDatAdd(uChar8 uDevAdd,uChar8 uDatAdd)
  182. {
  183.         IIC_Start();                        // 发送开始信号
  184.         InputOneByte(uDevAdd);        // 输入器件地址
  185.         IIC_RdAck();                          // 读应答信号
  186.         InputOneByte(uDatAdd);        // 输入数据地址
  187.         IIC_RdAck();                        // 读应答信号
  188.         return TRUE;         
  189. }
  190. /* ***************************************************** */
  191. // 函数名称:IIC_RdDatFromAdd()
  192. // 函数功能:向IIC器件读数据
  193. // 入口参数:器件ID(uDevID)、数据存储地址(uStaAddVal)
  194. //                         待存数据(*p)、连续存储数据的个数(uiLenVal)
  195. // 出口参数:无
  196. /* ***************************************************** */
  197. void IIC_RdDatFromAdd(uChar8 uDevID, uChar8 uStaAddVal, uChar8 *p, uChar8 uiLenVal)
  198. {                                                   
  199.         uChar8 iCount;
  200.         IIC_WrDevAddAndDatAdd(uDevID | IIC_WRITE,uStaAddVal);  
  201.         IIC_Start();
  202.         InputOneByte(uDevID | IIC_READ);
  203.         // IIC_READ 为写命令后缀符
  204.         IIC_RdAck();     
  205.         for(iCount = 0;iCount < uiLenVal;iCount++)
  206.         {
  207.                 *p++ = OutputOneByte();
  208.                    if(iCount != (uiLenVal - 1))
  209.                         IIC_Ack();                 
  210.         }      
  211.         IIC_Nack();        
  212.         IIC_Stop();         
  213. }
  214. /* ***************************************************** */
  215. // 函数名称:LM75A_ReadReg()
  216. // 函数功能:读LM75A任意寄存器值
  217. // 入口参数:寄存器地址(addr),uLenVal,读出字节的长度
  218. // 出口参数:寄存器内容(*val)
  219. /* ***************************************************** */
  220. void LM75A_ReadReg(uChar8 addr, uChar8 *val, uChar8 uLenVal)
  221. {
  222.         IIC_RdDatFromAdd(LM75ADevIDAddr, addr, val, uLenVal);
  223. }
  224. /* ***************************************************** */
  225. // 函数名称:LM75A_TempConv()
  226. // 函数功能:温度转换
  227. // 入口参数:无
  228. // 出口参数:无
  229. /* ***************************************************** */
  230. void LM75A_TempConv(void)
  231. {
  232.         uChar8 TempML[2]={0};                                                // 临时数值,用于存放Temp的高低字节
  233.         uInt16 uiTemp;                                                                // 用于存放Temp的11位字节数据
  234.         LM75A_ReadReg(0x00,TempML,2);                                // 读出温度,并存于数组TempHL中
  235.         uiTemp = (uInt16)TempML[0];                                        // 将高字节存入变量uiTemp中
  236.         uiTemp = (uiTemp << 8 | TempML[1]) >> 5;        // 接着并入后3位,最后右移5位就是11位补码数(8+3共11位)
  237.         /* ***** 首先判断温度是“0上”还是是“0下” ***** */        
  238.         if(!(TempML[0] & 0x80))                                                // 最高位为“0”则为“0上”
  239.         {
  240.                 p_bH0L_Flag = 0;
  241.                 p_fLM75ATemp = uiTemp * 0.125;        
  242.         }
  243.         else                                                                                // 这时为“0下”(p_fLM75ATemp)℃
  244.         {
  245.                 p_bH0L_Flag = 1;
  246.                 p_fLM75ATemp = (0x800 - uiTemp) * 0.125;// 由于计算机中负数是以补码形式存的,所以有这样的算法。
  247.         }
  248. }
  249. /* ***************************************************** */
  250. // 函数名称:UART_Init()
  251. // 函数功能:串口初始化
  252. // 入口参数:无
  253. // 出口参数:无
  254. /* ***************************************************** */
  255. void UART_Init(void)
  256. {
  257.         TMOD &= 0x0f;           // 清空定时器1      
  258.         TMOD |= 0x20;                // 定时器1工作于方式2
  259.         TH1 = 0xfd;                        // 为定时器1赋初值
  260.         TL1 = 0xfd;                        // 等价于将波特率设置为9600
  261.         ET1 = 0;                        // 防止中断产生不必要的干扰
  262.         TR1 = 1;                        // 启动定时器1
  263.         SCON |= 0x40;                // 串口工作于方式1,不允许接收
  264. }

  265. /***************************功能定义***************************/
  266. #define LCD12864_W_COM                        0xF8        //写指令
  267. #define LCD12864_R_COM                        0xFC        //读指令
  268. #define LCD12864_W_DAT                        0xFA        //写数据
  269. #define LCD12864_R_DAT                        0xFE        //读数据
  270. #ifndef __LCD12864_H__
  271. #define __LCD12864_H__
  272. #define LCD12864_COM 0        //输入指令
  273. #define LCD12864_DAT 1        //输入数据
  274. #define LCD12864_CLEAR                        0x01        //清除显示
  275. #define LCD12864_CURSOR                        0x02        //位址归位,游标回原点
  276. #define LCD12864_CURSOR_RLF                0x04        //光标左移,整体显示不移动
  277. #define LCD12864_CURSOR_RRF                0x06        //光标右移,整体显示不移动
  278. #define LCD12864_CURSOR_RLN                0x05        //光标左移,整体显示移动
  279. #define LCD12864_CURSOR_RRN                0x07        //光标右移,整体显示移动
  280. #define LCD12864_DIS_OFF                0x08        //显示状态全关
  281. #define LCD12864_DIS_ON                        0x0E        //显示状态开
  282. #define LCD12864_DIS_CUR_ON                0x0E        //游标显示开
  283. #define LCD12864_DIS_CURS_ON        0x0F        //游标位置显示开
  284. #define LCD12864_CURSOR_RL                0x10        //游标左移
  285. #define LCD12864_CURSOR_RR                0x14        //游标右移
  286. #define LCD12864_CURDIS_RL                0x18        //整体显示左移,光标跟随
  287. #define LCD12864_CURDIS_RR                0x1C        //整体显示又移,光标跟随
  288. #define LCD12864_COM_BASIC                0x30        //基本指令集动作
  289. #define LCD12864_COM_PLOT_ON        0x36        //扩展指令集动作,绘图显示ON
  290. #define LCD12864_COM_PLOT_OFF        0x34        //扩展指令集动作,绘图显示OFF
  291. #define LCD12864_STAND_TO                0x31        //进入待命模式
  292. #define LCD12864_PLACE_ROLL                0x03        //允许输入卷动位址
  293. #define LCD12864_PLACE_IRAM                0x02        //允许输入IRAM位址
  294. #define LCD12864_REVERES_13                0x04        //选择一、三行同时作反白显示
  295. #define LCD12864_REVERES_24                0x05        //选择二、四行同时作反白显示
  296. #define LCD12864_REST_ON                0x08        //进入睡眠模式
  297. #define LCD12864_REST_OFF                0x0C        //脱离睡眠模式
  298. #define LCD12864_W_COM                        0xF8        //写指令
  299. #define LCD12864_R_COM                        0xFC        //读指令
  300. #define LCD12864_W_DAT                        0xFA        //写数据
  301. #define LCD12864_R_DAT                        0xFE        //读数据
  302. //======串口模式=======
  303. sbit LCD12864_CS = P2^7;   //片选信号输入
  304. sbit LCD12864_STD = P2^6;  //串行数据输入
  305. sbit LCD12864_SCLK = P2^5; //串行移位脉冲输入
  306. sbit LCD12864_PSB = P2^4;  //串并模式选择 0:串口,1:并口
  307. sbit LCDRST  = P2^3;
  308. unsigned char code tabe[10]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//查表法//0-9数字
  309. /*****************************向12864写入8位数据*************************************/
  310. void LCD12864_Wbyte(uchar byte)
  311. {
  312.         uchar i;

  313.         for(i=0;i<8;i++)
  314.                 {
  315.                 LCD12864_SCLK = 0;
  316.                 byte <<= 1;                         //左移待写入数据,使最高位移至CY
  317.                 LCD12864_STD = CY;        //写入一位数据
  318.                 LCD12864_SCLK = 1;
  319.                 LCD12864_SCLK = 0;   
  320.                 }
  321. }
  322. /***************************从12864读出8位数据***返回:sdat************************************/
  323. uchar LCD12864_Rbyte(void)
  324. {
  325.      uchar i,sdat,temp1,temp2;
  326.      temp1 = 0;
  327.      temp2 = 0;
  328. //==========12864的串行数据输出形式是D7-D6-D5-D4-0-0-0-0-D3-D2-D1-D0-0-0-0-0,故要度两个八位整合==============
  329.      for(i=0;i<8;i++)
  330.                 {
  331.                 temp1=temp1 << 1;
  332.                 LCD12864_SCLK = 0;
  333.                 LCD12864_SCLK = 1;            
  334.                 LCD12864_SCLK = 0;
  335.                 if( LCD12864_STD )        temp1|=0x01;        //tempe1:D7-D6-D5-D4-0-0-0-0
  336.                 }
  337.      for(i=0;i<8;i++)
  338.                 {
  339.                 temp2=temp2 << 1;
  340.                 LCD12864_SCLK = 0;
  341.                 LCD12864_SCLK = 1;            
  342.                 LCD12864_SCLK = 0;
  343.                 if( LCD12864_STD ) temp2|=0x01;   //tempe2:D3-D2-D1-D0-0-0-0-0
  344.                 }
  345.         sdat = ((temp1 & 0xf0)|(temp2 >> 4));  //取出D7\D6\D5\D4\D3\D2\D1\D0                    
  346.         return sdat;  //返回一个值(sdat)
  347. }
  348. /****************************读忙状态**************************************/
  349. void LCD12864_busy( void )
  350. {
  351.         do        LCD12864_Wbyte( LCD12864_R_COM );                //LCD12864_RW=11111,RW(1),RS(0),0
  352.         while( LCD12864_Rbyte() & 0x80 );         //读BF,直到BF == 0
  353. }
  354. /*************************dat_com=0写指令,dat_com=1写数据*****************************************/
  355. void LCD12864_W (bit dat_com,uchar byte)
  356. {
  357.         uchar temp;
  358.         if(dat_com == 0)         //为零,写入指令
  359.                 temp = LCD12864_W_COM;        //11111,RS(0),RW(0),0
  360.         else                            //否则,写入数据
  361.                 temp = LCD12864_W_DAT;        //11111,RS(1),RW(0),0
  362.         LCD12864_CS = 1;                //片选使能
  363.         LCD12864_busy();                //LCD忙检测
  364.         LCD12864_Wbyte(temp);        //写入模式选择,指令还是数据
  365.         LCD12864_Wbyte(byte&0xf0);        //写入字节
  366.         LCD12864_Wbyte((byte<<4)&0xf0);        //写入字节
  367.     LCD12864_CS = 0;                //片选关闭
  368. }
  369. /****************************LCD12864初始化**************************************/

  370. void LCD12864_Init(void)
  371. {
  372.         LCDRST=1;
  373.         LCD12864_PSB = 0;        //选择串口模式
  374.         LCD12864_W(LCD12864_COM,0x30);        //基本指令功能.
  375.         LCD12864_W(LCD12864_COM,0x03);        //允许输入卷动位址
  376.         LCD12864_W(LCD12864_COM,0x0c);                //脱离随眠状态,显示打开,关光标,反白关.
  377.         LCD12864_W(LCD12864_COM,0x01);                //清屏指令.
  378.         LCD12864_W(LCD12864_COM,0x06);        //AC自动加一,光标右移,整体显示不移动   
  379. }
  380. /**************************LCD12864字符位置自定义显示****************************************/
  381. void LCD12864_WPoss(uchar x,uchar y,uchar *buff)
  382. {
  383.         uchar addr,i=0;
  384.         switch (x)
  385.                 {
  386.                 case 0:addr=0x80;break;
  387.                 case 1:addr=0x90;break;
  388.                 case 2:addr=0x88;break;
  389.                 case 3:addr=0x98;break;
  390.                 }
  391.         addr=addr+y;

  392.         LCD12864_W(LCD12864_COM,LCD12864_COM_BASIC);        //8BitMCU,基本指令集合
  393.         LCD12864_W(LCD12864_COM,addr);                                        //显示在自定义位置

  394.         while(buff[i]!='\0')
  395.                 {       
  396.                 LCD12864_W(LCD12864_DAT,buff[i++]);
  397.                 if(++y==16)
  398.                         {
  399.                         y=0;
  400.                         if(++x==4) x=0;

  401.                         switch (x)
  402.                                 {
  403.                                 case 0:addr=0x80;break;
  404.                                 case 1:addr=0x90;break;
  405.                                 case 2:addr=0x88;break;
  406.                                 case 3:addr=0x98;break;
  407.                                 }
  408.                         addr=addr+y;
  409.                         LCD12864_W(LCD12864_COM,addr);
  410.                         }
  411.        
  412.                 }
  413. }
  414. void Disp_img(unsigned char  *img)        //图形方式12864显示字模221 横向取膜
  415. {
  416.         unsigned char i,j;
  417.         unsigned int k = 0;

  418.         LCD12864_W(0,0x36); //图形方式
  419.         for(i=0;i<32;i++)
  420.           {
  421.                 LCD12864_W(0,0x80+i);
  422.                 LCD12864_W(0,0x80);
  423.             for(j=0;j<16;j++)
  424.                 {
  425.                         LCD12864_W(1,img[k++]);
  426.                 }
  427.           }

  428.         for(i=0;i<32;i++)
  429.           {
  430.                 LCD12864_W(0,0x80+i);
  431.                 LCD12864_W(0,0x88);
  432.             for(j=0;j<16;j++)
  433.                 {
  434.                         LCD12864_W(1,img[k++]);
  435.                   }
  436.         }
  437. }
  438. /************************显示11************************************/

  439. void display1(long temp)
  440. {
  441.     uchar dt1,dt2,dt3,dt4,dt5,dt6,dt7,dt8;
  442.         //temp=12345678;
  443.         dt1 = temp%10;//1位
  444.         dt2 = temp%100/10;//2位
  445.         dt3 = temp%1000/100;//3位
  446.         dt4 = temp%10000/1000;//4位

  447.         dt5 = temp%100000/10000;//5位
  448.         dt6 = temp%1000000/100000;//6位
  449.         dt7 = temp%10000000/1000000;//7位
  450.         dt8 = temp/10000000;//8位             最高位  

  451.         LCD12864_WPoss(3,0,"温度:");//第1行显示表1
  452.     // LCD12864_W(0,0x80+3);//LCD12864_W ((0或1),****)  0写指令  1写数据

  453.      //LCD12864_W(1,tabe[dt8]);//6位
  454.      //LCD12864_W(1,tabe[dt7]);//5位
  455.      //LCD12864_W(1,tabe[dt6]);//4位
  456.      LCD12864_W(1,tabe[dt5]);//3位       
  457.            LCD12864_W(1,tabe[dt4]);//4位
  458.                  LCD12864_W(1,0x2e);
  459.      LCD12864_W(1,tabe[dt3]);//3位
  460.            //LCD12864_W(1,tabe[dt2]);//4位
  461.      //LCD12864_W(1,tabe[dt1]);//3位
  462.      LCD12864_WPoss(3,5,"C");//第1行显示表1
  463.                  LCD12864_WPoss(0,0,"  LM75A 温度计");//第1行显示表1
  464.                 LCD12864_WPoss(1,0,"IIC 地址:0X90   ");//第1行显示表1
  465.     LCD12864_WPoss(2,0,"  传感器:LM75A");//第1行显示表1

  466. }
  467. /* ***************************************************** */
  468. // 函数名称:main()
  469. // 函数功能:读取LN75A温度值,数码管显示并串口打印
  470. // 入口参数:无
  471. // 出口参数:无
  472. /* ***************************************************** */
  473. void main()
  474. {
  475.         
  476.         uChar8 i;
  477.         UART_Init();
  478.               LCD12864_Init();       
  479.         while(1)
  480.         {
  481.                                
  482.                                        
  483.                  LM75A_TempConv();//读取温度LM75A  
  484.                  DelayMS(200);
  485.                                        
  486.                  LM75WD = p_fLM75ATemp * 1000;// 将温度全部转换成整数,以便数码管显示                               
  487.                 display1(LM75WD);//显示温度 //Ok         
  488.                                        
  489.        
  490.         }
  491. }
复制代码

所有资料51hei提供下载:
128显STC89C LM75A温度OK.zip (55.38 KB, 下载次数: 49)

评分

参与人数 3黑币 +65 收起 理由
chentianyuan + 3 淡定
YJGG + 12 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:479459 发表于 2019-3-22 14:17 | 只看该作者
终于寻到了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表