找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2167|回复: 5
收起左侧

单片机+ntc温度计使用1602液晶显示测试成功,转段码屏不不能显示,是什么问题?求解

[复制链接]
ID:858009 发表于 2021-10-12 16:56 | 显示全部楼层 |阅读模式
1602液晶显示成功程序:
  1. #include<reg52.h>                                 //头文件
  2. #include<intrins.h>
  3. #include "math.h"
  4. #define uchar unsigned char                 //宏定义
  5. #define uint unsigned int                 //宏定义
  6. #define LCD1602_dat P0                         //LCD1602的数据传输IO口

  7. sbit LCD1602_rs=P3^5;//LCD1602命令数据控制IO
  8. sbit LCD1602_rw=P3^6; //LCD1602读写IO控制
  9. sbit LCD1602_e=P3^4;  //数据脉冲输入

  10. sbit DIN  = P2^0;        //串行数据输入端
  11. sbit DCLK  = P2^1;        //I/O时钟输入
  12. sbit DOUT = P2^5;   //串行数据输出端
  13. sbit CS   = P3^7;        //片选脚IO

  14. #define  AD_CH3 0xe4

  15. float zhi;        //暂存读取的输入变量

  16. int temp;        //读取热敏温度计的温度数据

  17. void delay(uint T)                //系统延时程序
  18. {
  19.         while(T--);
  20. }

  21. /*=========================================
  22. 函数   :SPI_Write(uchar DAT)
  23. 参数   :DAT需要发送的数据
  24. 返回值 :无
  25. 描述   :发送一个字节数据
  26. ==========================================*/
  27. void SPI_Write(uchar DAT)
  28. {
  29.         uchar i;
  30.         for(i=0;i<8;i++)     //分别写8次,每次写一位
  31.         {
  32.                 DCLK = 0;        //拉低时钟总,允许DIN变化
  33.                 if(DAT & 0x80)   //先写数据最高位
  34.                         DIN = 1;     //写1
  35.                 else
  36.                         DIN = 0;     //写0
  37.                 DCLK = 1;        //拉高时钟,让从位机读取DIN        
  38.                 DAT <<=1;
  39.         }
  40. }
  41. /*========================================
  42. 函数   :ReadByte()
  43. 参数   :无
  44. 返回值 :返回读出的数据
  45. =========================================*/
  46. uint SPI_Read()
  47. {
  48.         uchar i;
  49.         uint DAT;
  50.         for(i=0;i<12;i++)  //分别读12次,每次读一位
  51.         {
  52.                 DAT <<=1;      //数据左移一位,准备接收一位
  53.                 DCLK = 1;      //拉高时钟总线,读取SDA上的数据
  54.                 DCLK = 0;      //拉低时钟总线,允许从机控制SDA变化
  55.                 if(DOUT)
  56.                 DAT |= 0x01;   //为1则写1,否则不执行写1,通过左移补零
  57.         }
  58.         return(DAT);   //返回读出的数据
  59. }
  60. /*=======================================
  61. 返回值 :AD转出的数字量
  62. 描述   :读指定通道的输入的模拟量转为数字量
  63. ========================================*/
  64. uint ReadAD(uchar cmd)
  65. {
  66.         uint DAT;
  67.         CS = 0;
  68.         SPI_Write(cmd);
  69.         DCLK = 0;        //拉低时钟总线
  70.         _nop_();
  71.         _nop_();
  72.         _nop_();
  73.         _nop_();
  74.         _nop_();
  75.         DAT = SPI_Read();
  76.         CS = 1;
  77.         return(DAT);    //返回读出数据
  78. }
  79. /********************************************************************
  80. * 名称 : LCD1602_write(uchar order,dat)
  81. * 功能 : 1602写如数据函数
  82. * 输入 : 输入的命令值
  83. * 输出 : 无
  84. ***********************************************************************/
  85. void LCD1602_write(uchar order,dat)                                  //1602 一个字节  处理
  86. {
  87.     LCD1602_e=0;
  88.     LCD1602_rs=order;
  89.     LCD1602_dat=dat;
  90.     LCD1602_rw=0;
  91.     LCD1602_e=1;
  92.     delay(1);
  93.     LCD1602_e=0;                                                                                                                                                                                                     
  94. }
  95. /********************************************************************
  96. * 名称 : LCD1602_writebye(uchar *prointer)
  97. * 功能 : 1602写入数据函数  指针式
  98. * 输入 : 输入的命令值
  99. ***********************************************************************/
  100. void LCD1602_writebyte(uchar *prointer)                                   //1602 字符串    处理
  101. {
  102.     while(*prointer!='\0')
  103.     {
  104.         LCD1602_write(1,*prointer);
  105.         prointer++;
  106.     }
  107. }
  108. /********************************************************************
  109. * 名称 : LCD1602_cls()
  110. * 功能 : 初始化1602液晶
  111. ***********************************************************************/
  112. void LCD1602_cls()                                                                         //1602 初始化
  113. {
  114.         LCD1602_write(0,0x01);     //1602 清屏 指令
  115.         delay(1500);
  116.         LCD1602_write(0,0x38);     // 功能设置 8位、5*7点阵
  117.         delay(1500);
  118.         LCD1602_write(0,0x0c);     //设置 光标   不显示开关、不显示光标、字符不闪烁
  119.         LCD1602_write(0,0x06);
  120.         LCD1602_write(0,0xd0);
  121.         delay(1500);
  122. }
  123. /********************************************************************
  124. * 名称 : show()
  125. * 功能 : LCD1602液晶显示程序
  126. ***********************************************************************/
  127. void show()                        //显示数据
  128. {
  129.                 LCD1602_write(0,0x80);                   //显示位置设定
  130.                 {
  131.                         LCD1602_write(1,0x30+temp/1000%10);           
  132.                         LCD1602_write(1,0x30+temp/100%10);
  133.                         LCD1602_write(1,0x30+temp/10%10);
  134.                 }
  135.                 LCD1602_write(1,0xdf);
  136.                 LCD1602_writebyte("C  ");
  137. }
  138. /********************************************************************
  139. * 名称 : float TempCalculate(float Rx,float B,float Revise,float BasicRx)
  140. * 功能 : 根据当前热敏电阻的阻值、以及参数、通过Sin曲线求出当前系统的温度值  并返回浮点型的温度值
  141. ***********************************************************************/
  142. float TempCalculate(float Rx,float B,float Revise,float BasicRx)
  143. {
  144. /*
  145. Rx:  热敏电阻当前阻值
  146. B:   热敏电阻参数B值
  147. Revise:  校正温度
  148. BasicRx:  热敏电阻25度时电阻(标称电阻数值)
  149. 返回: 摄氏度
  150. */  
  151.     Rx = Rx / BasicRx;
  152.     Rx = log(Rx);   
  153.     Rx = (Rx) / B;
  154.     Rx = Rx + 0.003356;
  155.     Rx = 1 / Rx;
  156.     Rx = Rx - 273.13;  
  157.     Rx = Rx + Revise;   
  158.     return Rx;
  159. }
  160. /********************************************************************
  161. * 名称 : void main()
  162. * 功能 : 系统主程序
  163. * 输入 : 无
  164. * 输出 : 无
  165. ***********************************************************************/
  166. void main()
  167. {
  168.         float Rad;               //生成运算暂存变量
  169.         LCD1602_cls();     //LCD1602初始化程序调用
  170.         while(1)
  171.         {
  172.                 zhi=(float)ReadAD(AD_CH3)/819.0;  //计算电压值
  173.                 Rad=zhi/((5.0-zhi)/10000.0);   //计算热敏电阻当前阻值
  174.                 temp=(int)((temp * 0.5) + (TempCalculate(Rad,3950.0,0,10000.0) * 0.5)*10);//求出当前系统的当前温度
  175.                 show();                 //显示函数
  176.         }
  177. }
复制代码



段码屏程序(不能显示对应的温度):

  1. #include <reg52.h>
  2. //#include <intrins.h>           //为了使用NOP
  3. #define NOP _nop_()
  4. #define uchar unsigned char                                                                                                                                                                                                                                      
  5. #define uint unsigned int
  6. #define ComMode 0x52  //4COM,1/3bias 1000 010 1001 0
  7. #define RCosc 0x30    //内部RC振荡器(上电默认)1000 0011 0000
  8. #define LCD_on 0x06   //打开LCD显示 偏压发生器1000 0000 0 11 0
  9. #define LCD_off 0x04  //关闭LCD显示(上电默认)
  10. #define Sys_en 0x02   //系统振荡器开 1000 0000 0010
  11. #define Ctrl_cmd 0x80 //写控制命令 1000
  12. #define Data_cmd 0xa0 //写数据命令 1010

  13. //定义HT1621端口
  14. #define SEG_NUM 27          //段码数字个数,即Seg数量/2

  15. sbit CS1=P1^0;
  16. sbit WR1=P1^1;
  17. sbit DATA1=P1^2;

  18. /**-------------------------------------------------------------------------
  19. Name: SendBit_1621(送数据程序)
  20. ---------------------------------------------------------------------------*/
  21. void SendBit_1621(uchar sdata,uchar cnt) //sdata 的高cnt 位写入HT1621,高位在前
  22. {
  23.         uchar i;
  24.         for(i=0;i<cnt;i++)
  25.         {
  26.                 WR1=0;         
  27.                 if(sdata&0x80) DATA1=1;
  28.                 else DATA1=0;
  29.                 WR1=1;
  30.                 sdata<<=1;
  31.         }
  32. }
  33. /**-------------------------------------------------------------------------
  34. Name: SendCmd(送命令)
  35. ---------------------------------------------------------------------------*/
  36. void SendCmd_1621(uchar command)
  37. {
  38.         CS1=0;
  39.         SendBit_1621(0x80,4);    //写入标志码“100”和9 位command 命令,由于
  40.         SendBit_1621(command,8); //没有使有到更改时钟输出等命令,为了编程方便
  41.         CS1=1;                   //直接将command 的最高位写“0”
  42. }
  43. /**-------------------------------------------------------------------------
  44. Name: Write_1621(送数据和命令程序)
  45. ---------------------------------------------------------------------------*/
  46. void Write_1621(uchar addr,uchar sdata,uchar len)
  47. {
  48.         addr<<=2;
  49.         CS1=0;
  50.         SendBit_1621(0xa0,3);  //写入标志码“101”
  51.         SendBit_1621(addr,6);  //写入addr 的高6位
  52.         SendBit_1621(sdata,len); //写入data 的高len位
  53.         CS1=1;
  54. }
  55. /**-------------------------------------------------------------------------
  56. Name: all_off(清除1621显示)
  57. ---------------------------------------------------------------------------*/
  58. void HT1621_all_off(void)
  59. {
  60.         uchar i;
  61.         uchar addr=0;
  62.         for(i=0;i<SEG_NUM;i++)
  63.         {
  64.                 Write_1621(addr,0x00,8);
  65.                 addr+=2;
  66.         }
  67. }
  68. /**-------------------------------------------------------------------------
  69. Name: Init_1621(初始化1621)
  70. -------------------------------------------------------------------------*/
  71. void Init_1621(void)
  72. {
  73.         SendCmd_1621(Sys_en);
  74.         SendCmd_1621(RCosc);
  75.         SendCmd_1621(ComMode);
  76.         SendCmd_1621(LCD_on);
  77. }

  78. 主程序:
  79. #include<reg52.h>                                 //头文件
  80. #include<intrins.h>
  81. #include "math.h"
  82. #include "HT1621.h"
  83. #define uchar unsigned char                 //宏定义
  84. #define uint unsigned int                 //宏定义
  85. sbit DIN  = P2^0;        //串行数据输入端
  86. sbit DCLK  = P2^1;        //I/O时钟输入
  87. sbit DOUT = P2^5;   //串行数据输出端
  88. sbit CS   = P3^7;        //片选脚IO
  89. uchar code tab1[10]= {0xF0,0x00,0xD0,0x90,0x20,0xB0,0xF0,0x10,0xF0,0xB0};
  90. uchar code tab2[10]= {0xA0,0xA0,0x60,0xE0,0xE0,0xC0,0xC0,0xA0,0xE0,0xE0};

  91. #define  AD_CH3 0xe4

  92. float zhi;        //暂存读取的输入变量

  93. int temp;        //读取热敏温度计的温度数据

  94. void delay(uint T)                //系统延时程序
  95. {
  96.         while(T--);
  97. }
  98. /*=========================================
  99. 函数   :SPI_Write(uchar DAT)
  100. 参数   :DAT需要发送的数据
  101. 返回值 :无
  102. 描述   :发送一个字节数据
  103. ==========================================*/
  104. void SPI_Write(uchar DAT)
  105. {
  106.         uchar i;
  107.         for(i=0;i<8;i++)     //分别写8次,每次写一位
  108.         {
  109.                 DCLK = 0;        //拉低时钟总,允许DIN变化
  110.                 if(DAT & 0x80)   //先写数据最高位
  111.                         DIN = 1;     //写1
  112.                 else
  113.                         DIN = 0;     //写0
  114.                 DCLK = 1;        //拉高时钟,让从位机读取DIN        
  115.                 DAT <<=1;
  116.         }
  117. }
  118. /*========================================
  119. 函数   :ReadByte()
  120. 参数   :无
  121. 返回值 :返回读出的数据
  122. =========================================*/
  123. uint SPI_Read()
  124. {
  125.         uchar i;
  126.         uint DAT;
  127.         for(i=0;i<12;i++)  //分别读12次,每次读一位
  128.         {
  129.                 DAT <<=1;      //数据左移一位,准备接收一位
  130.                 DCLK = 1;      //拉高时钟总线,读取SDA上的数据
  131.                 DCLK = 0;      //拉低时钟总线,允许从机控制SDA变化
  132.                 if(DOUT)
  133.                 DAT |= 0x01;   //为1则写1,否则不执行写1,通过左移补零
  134.         }
  135.         return(DAT);   //返回读出的数据
  136. }
  137. /*=======================================
  138. 函数   :PCF8591Read(uchar cmd)
  139. 参数   :cmd XPT2046控制字节
  140. 返回值 :AD转出的数字量
  141. 描述   :读指定通道的输入的模拟量转为数字量
  142. ========================================*/
  143. uint ReadAD(uchar cmd)
  144. {
  145.         uint DAT;
  146.         CS = 0;
  147.         SPI_Write(cmd);
  148.         DCLK = 0;        //拉低时钟总线
  149.         _nop_();
  150.         _nop_();
  151.         _nop_();
  152.         _nop_();
  153.         _nop_();
  154.         DAT = SPI_Read();
  155.         CS = 1;
  156.         return(DAT);    //返回读出数据
  157. }
  158. /********************************************************************
  159. * 名称 : show()
  160. * 功能 : 液晶段码屏显示程序
  161. ***********************************************************************/
  162. void show()                        //显示数据
  163. {
  164.         Write_1621(15,tab1[temp/100],4);
  165.         Write_1621(16,tab2[temp/100],4);
  166.         Write_1621(17,tab1[temp/10%10],4);
  167.         Write_1621(18,tab2[temp/10%10],4);
  168.         Write_1621(19,tab1[temp%10],4);
  169.         Write_1621(20,tab2[temp%10],4);
  170. }
  171. /********************************************************************
  172. * 名称 : float TempCalculate(float Rx,float B,float Revise,float BasicRx)
  173. * 功能 : 根据当前热敏电阻的阻值、以及参数、通过Sin曲线求出当前系统的温度值  并返回浮点型的温度值***********************************************************************/
  174. float TempCalculate(float Rx,float B,float Revise,float BasicRx)
  175. {
  176. /*
  177. Rx:  热敏电阻当前阻值
  178. B:   热敏电阻参数B值
  179. Revise:  校正温度
  180. BasicRx:  热敏电阻25度时电阻(标称电阻数值)
  181. 返回: 摄氏度
  182. */  
  183.     Rx = Rx / BasicRx;   
  184.     Rx = log(Rx);
  185.     Rx = (Rx) / B;
  186.     Rx = Rx + 0.003356;
  187.     Rx = 1 / Rx;
  188.     Rx = Rx - 273.13;  
  189.     Rx = Rx + Revise;
  190.     return Rx;
  191. }
  192. /********************************************************************
  193. * 名称 : void main()
  194. * 功能 : 系统主程序
  195. ***********************************************************************/
  196. void main()
  197. {
  198.         float Rad;               //生成运算暂存变量
  199.         Init_1621();
  200.         HT1621_all_off();
  201.         while(1)
  202.         {
  203.                 zhi=(float)ReadAD(AD_CH3)/819.0;  //计算电压值
  204.                 Rad=zhi/((5.0-zhi)/10000.0);   //计算热敏电阻当前阻值
  205.                 temp=(int)((temp * 0.5) + (TempCalculate(Rad,3950.0,0,10000.0) * 0.5)*10);//求出当前系统的当前温度
  206.                 show();                 //显示函数
  207.         }
  208. }
复制代码



回复

使用道具 举报

ID:154281 发表于 2021-10-12 20:35 | 显示全部楼层
电路图发出来,看下你电路
回复

使用道具 举报

ID:213173 发表于 2021-10-13 07:11 | 显示全部楼层
不显示和不能正确显示是两回事。不显示通常是驱动函数问题,不能正确显示是段码与屏段位不符。以下是实际使用中的1款HT1621.C文件。芯片型号STC15W404AS。
  1. #include <STC15F2K60S2.H>
  2. #include <intrins.h>

  3. /*7段数码段对应的8Bit顺序依次为bit7~bit0:abcx_fged
  4.     --01--
  5.    |      |
  6.    10     02   08
  7.    |--20--|
  8.    40     04   08
  9.    |      |
  10.     --80--       
  11. */
  12. /*----------------------------
  13. LCD操作相关的宏定义和函数声明
  14. ----------------------------*/
  15. #define ComMode  0x52    //4COM,1/3bias                1000 0101 0010
  16. //#define ComMode  0x50    //4COM,1/2bias          1000 0101 0000
  17. #define RCosc    0x30    //内部RC振荡器(上电默认)1000 0011 0000
  18. #define LCD_on   0x06    //打开LCD显示 偏压发生器1000 0000 0110
  19. #define LCD_off  0x04    //关闭LCD显示(上电默认)
  20. #define Sys_en   0x02    //系统振荡器开 1000 0000 0010
  21. #define Ctrl_cmd 0x80    //写控制命令   1000
  22. #define Data_cmd 0xa0    //写数据命令   1010

  23. sbit DIPIN=P3^7;              //LCD液晶屏DI引脚
  24. sbit CLKPIN=P3^6;             //LCD液晶屏CLK引脚
  25. sbit CSPIN=P3^5;              //LCD液晶屏CS引脚

  26. //SMS0707B LCD Drive code
  27. //Write bit data 写位数据
  28. void SendBit_1621(unsigned char sdata,unsigned char cnt) //sdata 的高cnt 位写入HT1621,高位在前
  29. {
  30.         unsigned char i;
  31.         for(i=0;i<cnt;i++)
  32.         {
  33.                 CLKPIN=0;         
  34.                 if(sdata&0x80)
  35.                         DIPIN=1;
  36.                 else DIPIN=0;
  37.                 CLKPIN=1;
  38.                 sdata<<=1;
  39.         }
  40. }
  41. /*-------------------------------------------------------------------------
  42. Name: SendCmd(送命令)
  43. 写入标志码"100"和9位comma命令,由于没有使用到更改时钟输出等命令
  44. 为了编程方便直接将command 的最高位写"0"
  45. ---------------------------------------------------------------------------*/
  46. void SendCmd_1621(unsigned char command)//写命令
  47. {//3位标志码 + 9位命令,共12位
  48.         CSPIN=0; //执行一个下降沿                                       
  49.         SendBit_1621(0x80,4);    //写入标志码"100"和9位comma命令的最高1位共4位
  50.         SendBit_1621(command,8); //写入9位comma命令的后8位,组成1000 xxxx xxxx
  51.         CSPIN=1;//送数完成后置高电平
  52. }
  53. /**-------------------------------------------------------------------------
  54. Name: Write_1621(送命令和数据程序)
  55. 写入标志码"101"和6位addr地址码和8位sdata显示数据。
  56. ---------------------------------------------------------------------------*/
  57. void Write_1621(unsigned char addr,unsigned char sdata,unsigned char len)//写数据
  58. {//3位标志码 + 6位写数据命令 + 8(4)位数据,共17位
  59.         addr<<=2;//高6位有效
  60.         CSPIN=0; //执行一个下降沿
  61.         SendBit_1621(0xa0,3);                //写入标志码"101"    写数据命令101
  62.         SendBit_1621(addr,6);                //写入addr 的高6位   写数据命令xxxx xx
  63.         SendBit_1621(sdata,len);        //写入8/4位 sdata数据  len=8/4
  64.         CSPIN=1;//送数完成后置高电平
  65. }
  66. /**-------------------------------------------------------------------------
  67. Name: Init_1621(初始化1621)
  68. -------------------------------------------------------------------------*/
  69. void LCD_Init()                                                //初始化
  70. {//程序输入100 0+8=9位命令
  71.         SendCmd_1621(Sys_en);//Sys_en 0x02 系统振荡器开          100 0 0000 0010
  72.         SendCmd_1621(RCosc); //RCosc 0x30 内部RC振荡器(上电默认) 100 0 0011 0000
  73.         SendCmd_1621(ComMode);//4COM,1/3bias                     100 0 0101 0020
  74.         SendCmd_1621(LCD_on);//LCD_on 0x06 打开LCD显示 偏压发生器100 0 0000 0110
  75. }
  76. /*-------------------------------------------------------------------------
  77. Name: lcdwd1(点亮1621全部Seg)
  78. -------------------------------------------------------------------------*/
  79. void LCDWD1(void)
  80. {
  81.         unsigned char i;
  82.         unsigned char addr=9;//5位显示码寄存器起始地址0x09
  83.         for(i=0;i<5;i++)
  84.         {
  85.                 Write_1621(addr,LCD_Buffer[i+1],8);//addr为地址码,l_data为数据,8为8位数据
  86.                 addr+=2;//顺延2个4位地址码
  87.         }
  88. }

复制代码
回复

使用道具 举报

ID:858009 发表于 2021-10-13 09:57 | 显示全部楼层
wulin 发表于 2021-10-13 07:11
不显示和不能正确显示是两回事。不显示通常是驱动函数问题,不能正确显示是段码与屏段位不符。以下是实际使 ...

不能正确显示温度,只显示000
回复

使用道具 举报

ID:213173 发表于 2021-10-13 19:04 | 显示全部楼层
qwettyuio 发表于 2021-10-13 09:57
不能正确显示温度,只显示000

只显示000不能充分说明不能正确显示,而是要输入已知的数字,看显示结果。
回复

使用道具 举报

ID:1064915 发表于 2023-7-4 11:10 | 显示全部楼层
没有段码屏的逻辑表
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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