找回密码
 立即注册

QQ登录

只需一步,快速开始

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

求大神帮忙看看51单片机数码管显示温度出现残影闪烁的问题

[复制链接]
跳转到指定楼层
楼主
ID:1045483 发表于 2022-9-21 23:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在时钟显示状态下没有什么问题,按k4按键会进入温度显示状态,松开则取消。但是显示温度时数码管会一直出现闪烁的残影,就是正常的温度夹杂闪烁的残影,好像在不停扫描一样,有没有大佬帮忙看看哪里有问题?时钟显示正常,不会有闪烁的残影。代码放下面了。


单片机源程序如下:
  1. #include <REGX52.H>
  2. unsigned char KeyNum,MODE1=-1,MODE2=-1,TimeSetSelect=-1,TimeSetFlashFlag,alarmSetSelect=-1,alarmSetSelectflash,Clocklock=0,alarmlock=0,Tlock=0;
  3. char Hour=12,Min=00,Sec=02;
  4. int T;

  5. void Nixie(unsigned char Location,Number);
  6. void TimeShow(void)//时间显示功能
  7. {if(Clocklock==1){
  8.                 DS1302_ReadTime();//读取时间
  9.                 Nixie(1,DS1302_Time[0]/10);
  10.                 Nixie(2,DS1302_Time[0]%10);
  11.                 Nixie(4,DS1302_Time[1]/10);
  12.                 Nixie(5,DS1302_Time[1]%10);
  13.                 Nixie(7,DS1302_Time[2]/10);
  14.                 Nixie(8,DS1302_Time[2]%10);
  15.                 Nixie(3,17);
  16.                 Nixie(6,17);
  17. }
  18. }
  19.                

  20. void TimeSet(void)//时间设置功能
  21. {if(Clocklock==1){
  22.         if(KeyNum==1)//按键2按下
  23.         {
  24.                 TimeSetSelect++;//设置选择位加1
  25.                 TimeSetSelect%=3;//越界清零
  26.         }
  27.         if(KeyNum==3)//按键3按下
  28.         {
  29.                 DS1302_Time[TimeSetSelect]++;//时间设置位数值加1
  30.                 if(DS1302_Time[0]>23){DS1302_Time[0]=0;}//时越界判断
  31.                 if(DS1302_Time[1]>59){DS1302_Time[1]=0;}//分越界判断
  32.                 if(DS1302_Time[2]>59){DS1302_Time[2]=0;}//秒越界判断
  33.         }
  34.         if(KeyNum==4)//按键4按下
  35.         {
  36.                 DS1302_Time[TimeSetSelect]--;//时间设置位数值减1
  37.                 if(DS1302_Time[0]<0){DS1302_Time[0]=23;}//时越界判断
  38.                 if(DS1302_Time[1]<0){DS1302_Time[1]=59;}//分越界判断
  39.                 if(DS1302_Time[2]<0){DS1302_Time[2]=59;}//秒越界判断
  40.         }
  41.         //更新显示,根据TimeSetSelect和TimeSetFlashFlag判断可完成闪烁功能
  42.         if(TimeSetSelect==0 && TimeSetFlashFlag==1){Nixie(1,16);Nixie(2,16);Nixie(3,17);Nixie(6,17);}
  43.         else {Nixie(1,DS1302_Time[0]/10);Nixie(2,DS1302_Time[0]%10);Nixie(3,17);Nixie(6,17);}
  44.         if(TimeSetSelect==1 && TimeSetFlashFlag==1){Nixie(4,16);Nixie(5,16);Nixie(3,17);Nixie(6,17);}
  45.         else {Nixie(4,DS1302_Time[1]/10);Nixie(5,DS1302_Time[1]%10);Nixie(3,17);Nixie(6,17);}
  46.         if(TimeSetSelect==2 && TimeSetFlashFlag==1){Nixie(7,16);Nixie(8,16);Nixie(3,17);Nixie(6,17);}
  47.         else {Nixie(7,DS1302_Time[2]/10);Nixie(8,DS1302_Time[2]%10);Nixie(3,17);Nixie(6,17);}
  48. }
  49. }


  50. void alarmshow(void){//时间显示功能
  51. if(alarmlock==1){
  52.                 Nixie(1,Hour/10);
  53.                 Nixie(2,Hour%10);
  54.                 Nixie(4,Min/10);
  55.                 Nixie(5,Min%10);
  56.                 Nixie(7,Sec/10);
  57.                 Nixie(8,Sec%10);
  58.                 Nixie(3,17);
  59.                 Nixie(6,17);
  60. }
  61. }
  62. void alarmset(){
  63.         if(alarmlock==1){
  64.                 if(KeyNum==2)//按键2按下
  65.                 {
  66.                         alarmSetSelect++;//设置选择位加1
  67.                         alarmSetSelect%=3;//越界清零
  68.                 }
  69.                 if(KeyNum==3)//按键3按下
  70.                 {
  71.                                 if(alarmSetSelect==0){
  72.                                         Hour++;
  73.                                         if(Hour>23){Hour=0;};
  74.                         }else if(alarmSetSelect==1){
  75.                                                         Min++;
  76.                                        if(Min>23){Min=0;};
  77.                         }else{
  78.                                                 Sec++;
  79.                                                 if(Sec>23){Sec=0;};
  80.                         }
  81.                 }
  82.                 if(KeyNum==4)//按键4按下
  83.                 {
  84.                         switch(alarmSetSelect){
  85.                                 case 0:Hour--;
  86.                                        if(Hour<0){Hour=23;}
  87.                                                          break;
  88.                                 case 1:Min--;
  89.                                        if(Min<0){Min=59;}
  90.                                                          break;        
  91.                                 case 2:Sec--;
  92.                                        if(Sec<0){Sec=59;}
  93.                                                          break;                                                         
  94.                         }
  95.                 }
  96.                 if(alarmSetSelect==0 && alarmSetSelectflash==1){Nixie(1,16);Nixie(2,16);Nixie(3,17);Nixie(6,17);}
  97.                 else {Nixie(1,Hour/10);Nixie(2,Hour%10);Nixie(3,17);Nixie(6,17);}
  98.                 if(alarmSetSelect==1 && alarmSetSelectflash==1){Nixie(4,16);Nixie(5,16);Nixie(3,17);Nixie(6,17);}
  99.                 else {Nixie(4,Min/10);Nixie(5,Min%10);Nixie(3,17);Nixie(6,17);}
  100.                 if(alarmSetSelect==2 && alarmSetSelectflash==1){Nixie(7,16);Nixie(8,16);Nixie(3,17);Nixie(6,17);}
  101.                 else {Nixie(7,Sec/10);Nixie(8,Sec%10);Nixie(3,17);Nixie(6,17);}
  102. }
  103. }

  104. void TShow(){                                                
  105.                 if(Tlock==1){
  106.                                 DS18B20_ConvertT();        //转换温度
  107.                                 T=DS18B20_ReadT();        //读取温度
  108.                                 Nixie(6,T/10);
  109.                                 Nixie(7,T%10);
  110.                                 Nixie(8,12);
  111.                 }
  112.                                                                

  113. }



  114. void main()
  115. {
  116.         DS1302_Init();
  117.         Timer0Init();
  118.         DS1302_SetTime();//设置时间

  119.         
  120.         while(1)
  121.         {
  122.                 KeyNum=Key();//读取键码
  123.                 if(KeyNum==1)//按键1按下
  124.                 {
  125.                         MODE1++;
  126.                         Clocklock=1;
  127.                         alarmlock=0;
  128.                         Tlock=0;
  129.                 }
  130.                 switch(MODE1)//根据不同的功能执行不同的函数
  131.                 {
  132.                         case 0:TimeShow();
  133.                                                  if(P3_3==0){
  134.                                                          while(P3_3==0){
  135.                                                                                 Clocklock=0;
  136.                                                                           Tlock=1;
  137.                                                                           TShow();
  138.                                                          }
  139.                                                          Tlock=0;
  140.                                                 Clocklock=1;
  141.                                                 TimeShow();
  142.                         }
  143.                                                 break;
  144.                         case 1:TimeSet();DS1302_SetTime();break;
  145.                         case 2:TimeSet();DS1302_SetTime();break;
  146.                         case 3:TimeSet();DS1302_SetTime();break;
  147.                         case 4:MODE1=0;break;
  148.                 }
  149.                 if(KeyNum==2)//按键2按下
  150.                 {
  151.                         MODE2++;
  152.                         Clocklock=0;
  153.                         Tlock=0;
  154.                         TimeShow();
  155.                         alarmlock=1;
  156.                 }
  157.                 switch(MODE2)//根据不同的功能执行不同的函数
  158.                 {
  159.                         case 0:alarmshow();break;
  160.                         case 1:alarmset();break;
  161.                         case 2:alarmset();break;
  162.                         case 3:alarmset();break;
  163.                         case 4:MODE2=0;break;
  164.                 }
  165.                 if(DS1302_Time[0]==Hour&&DS1302_Time[1]==Min&&DS1302_Time[2]==Sec){
  166.                         int x;
  167.                         for(x=0,P2=0x01;x<25;x++){
  168.                                         P2=!P2;        //1111 1110
  169.                                         Delay(200);
  170.                         }
  171.                
  172.                 }
  173.         }
  174. }



  175. void Timer0_Routine() interrupt 1
  176. {
  177.         static unsigned int T0Count;
  178.         TL0 = 0x18;                //设置定时初值
  179.         TH0 = 0xFC;                //设置定时初值
  180.         T0Count++;
  181.         if(T0Count>=500)//每500ms进入一次
  182.         {
  183.                 T0Count=0;
  184.                 TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反
  185.           alarmSetSelectflash=!alarmSetSelectflash;//闪烁标志位取反
  186.         }
  187. }


  188. unsigned char Key()
  189. {
  190.         unsigned char KeyNumber=0;
  191.         
  192.         if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
  193.         if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
  194.         if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
  195.         if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
  196.         
  197.         return KeyNumber;
  198. }


  199. void Timer0Init(void)
  200. {
  201.         TMOD &= 0xF0;                //设置定时器模式
  202.         TMOD |= 0x01;                //设置定时器模式
  203.         TL0 = 0x18;                //设置定时初值
  204.         TH0 = 0xFC;                //设置定时初值
  205.         TF0 = 0;                //清除TF0标志
  206.         TR0 = 1;                //定时器0开始计时
  207.         ET0=1;
  208.         EA=1;
  209.         PT0=0;
  210. }


  211. void Delay(unsigned int xms)
  212. {
  213.         unsigned char i, j;
  214.         while(xms--)
  215.         {
  216.                 i = 2;
  217.                 j = 199;
  218.                 do
  219.                 {
  220.                         while (--j);
  221.                 } while (--i);
  222.         }
  223. }


  224. //引脚定义
  225. sbit DS1302_SCLK=P3^6;
  226. sbit DS1302_IO=P3^4;
  227. sbit DS1302_CE=P3^5;

  228. //寄存器写入地址/指令定义
  229. #define DS1302_SECOND                0x80
  230. #define DS1302_MINUTE                0x82
  231. #define DS1302_HOUR                        0x84
  232. #define DS1302_WP                        0x8E

  233. //时间数组,索引0~6分别为年、月、日、时、分、秒、星期,设置为有符号的便于<0的判断
  234. char DS1302_Time[]={12,59,25};

  235. /**
  236.   * @brief  DS1302初始化
  237.   * @param  无
  238.   * @retval 无
  239.   */
  240. void DS1302_Init(void)
  241. {
  242.         DS1302_CE=0;
  243.         DS1302_SCLK=0;
  244. }

  245. /**
  246.   * @brief  DS1302写一个字节
  247.   * @param  Command 命令字/地址
  248.   * @param  Data 要写入的数据
  249.   * @retval 无
  250.   */
  251. void DS1302_WriteByte(unsigned char Command,Data)
  252. {
  253.         unsigned char i;
  254.         DS1302_CE=0;
  255.         DS1302_SCLK=0;
  256.                 DS1302_CE=1;
  257.         for(i=0;i<8;i++)
  258.         {
  259.                 DS1302_IO=Command&(0x01<<i);
  260.                 DS1302_SCLK=1;
  261.                 DS1302_SCLK=0;
  262.         }
  263.         for(i=0;i<8;i++)
  264.         {
  265.                 DS1302_IO=Data&(0x01<<i);
  266.                 DS1302_SCLK=1;
  267.                 DS1302_SCLK=0;
  268.         }
  269. //        DS1302_CE=0;
  270. }

  271. /**
  272.   * @brief  DS1302读一个字节
  273.   * @param  Command 命令字/地址
  274.   * @retval 读出的数据
  275.   */
  276. unsigned char DS1302_ReadByte(unsigned char Command)
  277. {
  278.         unsigned char i,Data=0x00;
  279.         Command|=0x01;        //将指令转换为读指令
  280.         DS1302_CE=0;
  281.         DS1302_SCLK=0;
  282.         DS1302_CE=1;
  283.         for(i=0;i<8;i++)
  284.         {
  285.                 DS1302_IO=Command&(0x01<<i);
  286.                 DS1302_SCLK=0;
  287.                 DS1302_SCLK=1;
  288.         }
  289.         for(i=0;i<8;i++)
  290.         {
  291.                 DS1302_SCLK=1;
  292.                 DS1302_SCLK=0;
  293.                 if(DS1302_IO){Data|=(0x01<<i);}
  294.         }
  295.         DS1302_CE=0;
  296.         DS1302_SCLK=1;
  297.         DS1302_IO=0;        //读取后将IO设置为0,否则读出的数据会出错
  298.         DS1302_IO=1;
  299.         DS1302_CE=1;
  300.         return Data;
  301. }

  302. /**
  303.   * @brief  DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
  304.   * @param  无
  305.   * @retval 无
  306.   */
  307. void DS1302_SetTime(void)
  308. {
  309.         DS1302_WriteByte(DS1302_WP,0x00);
  310.         DS1302_WriteByte(DS1302_HOUR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);
  311.         DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[1]/10*16+DS1302_Time[1]%10);
  312.         DS1302_WriteByte(DS1302_SECOND,DS1302_Time[2]/10*16+DS1302_Time[2]%10);
  313.         DS1302_WriteByte(DS1302_WP,0x80);
  314. }

  315. /**
  316.   * @brief  DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
  317.   * @param  无
  318.   * @retval 无
  319.   */
  320. void DS1302_ReadTime(void)
  321. {
  322.         unsigned char Temp1;
  323.         Temp1=DS1302_ReadByte(DS1302_HOUR);
  324.         DS1302_Time[0]=Temp1/16*10+Temp1%16;
  325.         Temp1=DS1302_ReadByte(DS1302_MINUTE);
  326.         DS1302_Time[1]=Temp1/16*10+Temp1%16;
  327.         Temp1=DS1302_ReadByte(DS1302_SECOND);
  328.         DS1302_Time[2]=Temp1/16*10+Temp1%16;

  329. }


  330. unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00,0X40};

  331. void Nixie(unsigned char Location,Number){
  332.         switch(Location){
  333.                 case 1:P2_4=1;P2_3=1;P2_2=1;break;
  334.                 case 2:P2_4=1;P2_3=1;P2_2=0;break;
  335.                 case 3:P2_4=1;P2_3=0;P2_2=1;break;
  336.                 case 4:P2_4=1;P2_3=0;P2_2=0;break;
  337.                 case 5:P2_4=0;P2_3=1;P2_2=1;break;
  338.                 case 6:P2_4=0;P2_3=1;P2_2=0;break;
  339.                 case 7:P2_4=0;P2_3=0;P2_2=1;break;
  340.                 case 8:P2_4=0;P2_3=0;P2_2=0;break;
  341. }
  342.                 P0=NixieTable[Number];
  343.                         Delay(1);
  344.                         P0=0X00;
  345. }


  346. //引脚定义
  347. sbit OneWire_DQ=P3^7;

  348. /**
  349.   * @brief  单总线初始化
  350.   * @param  无
  351.   * @retval 从机响应位,0为响应,1为未响应
  352.   */
  353.         void Delay5us(){        //Delay 5us
  354. }

  355. void Delay500us()                //Delay 500us
  356. {
  357.         unsigned char i;

  358.         _nop_();
  359.         i = 227;
  360.         while (--i);
  361. }

  362. void Delay70us()                //Delay 70us
  363. {
  364.         unsigned char i;

  365.         _nop_();
  366.         i = 29;
  367.         while (--i);
  368. }

  369. void Delay10us()                //Delay 10us
  370. {
  371.         unsigned char i;

  372.         i = 2;
  373.         while (--i);
  374. }

  375. void Delay50us()                //@11.0592MHz
  376. {
  377.         unsigned char i;

  378.         _nop_();
  379.         i = 20;
  380.         while (--i);
  381. }

  382.         
  383.         
  384.         
  385.         
  386. unsigned char OneWire_Init(void)
  387. {
  388. //        unsigned char i;
  389.         unsigned char AckBit;
  390.         OneWire_DQ=1;
  391.         OneWire_DQ=0;
  392.         Delay500us();                //Delay 500us
  393.         OneWire_DQ=1;
  394.         Delay70us()        ;                //Delay 70us
  395.         AckBit=OneWire_DQ;
  396.         Delay500us()        ;        //Delay 500us
  397.         return AckBit;
  398. }

  399. /**
  400.   * @brief  单总线发送一位
  401.   * @param  Bit 要发送的位
  402.   * @retval 无
  403.   */
  404. void OneWire_SendBit(unsigned char Bit)
  405. {
  406. //        unsigned char i;
  407.         OneWire_DQ=0;
  408.         Delay10us();                        //Delay 10us
  409.         OneWire_DQ=Bit;
  410.         Delay50us();                        //Delay 50us
  411.         OneWire_DQ=1;
  412. }

  413. /**
  414.   * @brief  单总线接收一位
  415.   * @param  无
  416.   * @retval 读取的位
  417.   */
  418. unsigned char OneWire_ReceiveBit(void)
  419. {
  420. //        unsigned char i;
  421.         unsigned char Bit;
  422.         OneWire_DQ=0;
  423.         Delay5us();                        //Delay 5us
  424.         OneWire_DQ=1;
  425.         Delay5us();                        //Delay 5us
  426.         Bit=OneWire_DQ;
  427.         Delay50us();                        //Delay 50us
  428.         return Bit;
  429. }

  430. /**
  431.   * @brief  单总线发送一个字节
  432.   * @param  Byte 要发送的字节
  433.   * @retval 无
  434.   */
  435. void OneWire_SendByte(unsigned char Byte)
  436. {
  437.         unsigned char i;
  438.         for(i=0;i<8;i++)
  439.         {
  440.                 OneWire_SendBit(Byte&(0x01<<i));
  441.         }
  442. }

  443. /**
  444.   * @brief  单总线接收一个字节
  445.   * @param  无
  446.   * @retval 接收的一个字节
  447.   */
  448. unsigned char OneWire_ReceiveByte(void)
  449. {
  450.         unsigned char i;
  451.         unsigned char Byte=0x00;
  452.         for(i=0;i<8;i++)
  453.         {
  454.                 if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
  455.         }
  456.         return Byte;
  457. }


  458. //DS18B20指令
  459. #define DS18B20_SKIP_ROM                        0xCC
  460. #define DS18B20_CONVERT_T                        0x44
  461. #define DS18B20_READ_SCRATCHPAD         0xBE

  462. /**
  463.   * @brief  DS18B20开始温度变换
  464.   * @param  无
  465.   * @retval 无
  466.   */
  467. void DS18B20_ConvertT(void)
  468. {
  469.         OneWire_Init();
  470.         OneWire_SendByte(DS18B20_SKIP_ROM);
  471.         OneWire_SendByte(DS18B20_CONVERT_T);
  472. }

  473. /**
  474.   * @brief  DS18B20读取温度
  475.   * @param  无
  476.   * @retval 温度数值
  477.   */
  478. double DS18B20_ReadT(void)
  479. {
  480.         unsigned char TLSB,TMSB;
  481.         float Temp;
  482.         int T;
  483.                 OneWire_Init();
  484.         OneWire_SendByte(DS18B20_SKIP_ROM);
  485.         OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
  486.         TLSB=OneWire_ReceiveByte();
  487.                 TMSB=OneWire_ReceiveByte();
  488.         Temp=(TMSB<<8)|TLSB;
  489.                                                 T=Temp/16.0;
  490.                                                 return T;
  491.                
  492.         

  493.         
  494. }


  495. #include <REGX52.H>

  496. //引脚配置:
  497. sbit LCD_RS=P2^6;
  498. sbit LCD_RW=P2^5;
  499. sbit LCD_EN=P2^7;
  500. #define LCD_DataPort P0

  501. //函数定义:
  502. /**
  503.   * @brief  LCD1602延时函数,12MHz调用可延时1ms
  504.   * @param  无
  505.   * @retval 无
  506.   */
  507. void LCD_Delay()
  508. {
  509.         unsigned char i, j;

  510.         i = 2;
  511.         j = 239;
  512.         do
  513.         {
  514.                 while (--j);
  515.         } while (--i);
  516. }

  517. /**
  518.   * @brief  LCD1602写命令
  519.   * @param  Command 要写入的命令
  520.   * @retval 无
  521.   */
  522. void LCD_WriteCommand(unsigned char Command)
  523. {
  524.         LCD_RS=0;
  525.         LCD_RW=0;
  526.         LCD_DataPort=Command;
  527.         LCD_EN=1;
  528.         LCD_Delay();
  529.         LCD_EN=0;
  530.         LCD_Delay();
  531. }

  532. /**
  533.   * @brief  LCD1602写数据
  534.   * @param  Data 要写入的数据
  535.   * @retval 无
  536.   */
  537. void LCD_WriteData(unsigned char Data)
  538. {
  539.         LCD_RS=1;
  540.         LCD_RW=0;
  541.         LCD_DataPort=Data;
  542.         LCD_EN=1;
  543.         LCD_Delay();
  544.         LCD_EN=0;
  545.         LCD_Delay();
  546. }

  547. /**
  548.   * @brief  LCD1602设置光标位置
  549.   * @param  Line 行位置,范围:1~2
  550.   * @param  Column 列位置,范围:1~16
  551.   * @retval 无
  552.   */
  553. void LCD_SetCursor(unsigned char Line,unsigned char Column)
  554. {
  555.         if(Line==1)
  556.         {
  557.                 LCD_WriteCommand(0x80|(Column-1));
  558.         }
  559.         else if(Line==2)
  560.         {
  561.                 LCD_WriteCommand(0x80|(Column-1+0x40));
  562.         }
  563. }

  564. /**
  565.   * @brief  LCD1602初始化函数
  566.   * @param  无
  567.   * @retval 无
  568.   */
  569. void LCD_Init()
  570. {
  571.         LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
  572.         LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
  573.         LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
  574.         LCD_WriteCommand(0x01);//光标复位,清屏
  575. }

  576. /**
  577.   * @brief  在LCD1602指定位置上显示一个字符
  578.   * @param  Line 行位置,范围:1~2
  579.   * @param  Column 列位置,范围:1~16
  580.   * @param  Char 要显示的字符
  581.   * @retval 无
  582.   */
  583. void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
  584. {
  585.         LCD_SetCursor(Line,Column);
  586.         LCD_WriteData(Char);
  587. }

  588. /**
  589.   * @brief  在LCD1602指定位置开始显示所给字符串
  590.   * @param  Line 起始行位置,范围:1~2
  591.   * @param  Column 起始列位置,范围:1~16
  592.   * @param  String 要显示的字符串
  593.   * @retval 无
  594.   */
  595. void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
  596. {
  597.         unsigned char i;
  598.         LCD_SetCursor(Line,Column);
  599.         for(i=0;String[i]!='\0';i++)
  600.         {
  601.                 LCD_WriteData(String[i]);
  602.         }
  603. }

  604. /**
  605.   * @brief  返回值=X的Y次方
  606.   */
  607. int LCD_Pow(int X,int Y)
  608. {
  609.         unsigned char i;
  610.         int Result=1;
  611.         for(i=0;i<Y;i++)
  612.         {
  613.                 Result*=X;
  614.         }
  615.         return Result;
  616. }

  617. /**
  618.   * @brief  在LCD1602指定位置开始显示所给数字
  619.   * @param  Line 起始行位置,范围:1~2
  620.   * @param  Column 起始列位置,范围:1~16
  621.   * @param  Number 要显示的数字,范围:0~65535
  622.   * @param  Length 要显示数字的长度,范围:1~5
  623.   * @retval 无
  624.   */
  625. void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
  626. {
  627.         unsigned char i;
  628.         LCD_SetCursor(Line,Column);
  629.         for(i=Length;i>0;i--)
  630.         {
  631.                 LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
  632.         }
  633. }

  634. /**
  635.   * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  636.   * @param  Line 起始行位置,范围:1~2
  637.   * @param  Column 起始列位置,范围:1~16
  638.   * @param  Number 要显示的数字,范围:-32768~32767
  639.   * @param  Length 要显示数字的长度,范围:1~5
  640.   * @retval 无
  641.   */
  642. void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
  643. {
  644.         unsigned char i;
  645.         unsigned int Number1;
  646.         LCD_SetCursor(Line,Column);
  647.         if(Number>=0)
  648.         {
  649.                 LCD_WriteData('+');
  650.                 Number1=Number;
  651.         }
  652.         else
  653.         {
  654.                 LCD_WriteData('-');
  655.                 Number1=-Number;
  656.         }
  657.         for(i=Length;i>0;i--)
  658.         {
  659.                 LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
  660.         }
  661. }

  662. /**
  663.   * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  664.   * @param  Line 起始行位置,范围:1~2
  665.   * @param  Column 起始列位置,范围:1~16
  666.   * @param  Number 要显示的数字,范围:0~0xFFFF
  667.   * @param  Length 要显示数字的长度,范围:1~4
  668.   * @retval 无
  669.   */
  670. void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
  671. {
  672.         unsigned char i,SingleNumber;
  673.         LCD_SetCursor(Line,Column);
  674.         for(i=Length;i>0;i--)
  675.         {
  676.                 SingleNumber=Number/LCD_Pow(16,i-1)%16;
  677.                 if(SingleNumber<10)
  678.                 {
  679.                         LCD_WriteData(SingleNumber+'0');
  680.                 }
  681.                 else
  682.                 {
  683.                         LCD_WriteData(SingleNumber-10+'A');
  684.                 }
  685.         }
  686. }

  687. /**
  688.   * @brief  在LCD1602指定位置开始以二进制显示所给数字
  689.   * @param  Line 起始行位置,范围:1~2
  690.   * @param  Column 起始列位置,范围:1~16
  691.   * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  692.   * @param  Length 要显示数字的长度,范围:1~16
  693.   * @retval 无
  694.   */
  695. void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
  696. {
  697.         unsigned char i;
  698.         LCD_SetCursor(Line,Column);
  699.         for(i=Length;i>0;i--)
  700.         {
  701.                 LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
  702.         }
  703. }
复制代码

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

使用道具 举报

沙发
ID:213173 发表于 2022-9-22 07:23 | 只看该作者
楼主的问题是按键扫描函数干扰数码管动态显示。参考这个示例修改即可。
DS18B20温度上下限报警数码管 1602显示.rar (183.47 KB, 下载次数: 6)

回复

使用道具 举报

板凳
ID:123289 发表于 2022-9-22 09:12 | 只看该作者
方案:
1、程序中禁止用DELAY函数。理由:它占用CPU时间,影响其它程序运行。
2、显示的内容不要直接送LED显示端口,而是统一送入一个缓冲区,缓冲区字节数与LED数量一样,一一对应。理由:不同的程序要求的显示格式、方式可能不同,集中处理,显示不易出乱。
最后要的是:无论你如何变换显示内容,都不会拖尾、重影,因为还未送到LED。
3、写个显示程序,只从缓冲区中取数显示就可以了,单一而简单。
4、扫描显示注意以下次序:先关所有显示,再送出缓冲区中的段码,再打开所有显示。这样就无重影了。

写程序要先规划好方案。
回复

使用道具 举报

地板
ID:584814 发表于 2022-9-22 10:44 | 只看该作者
yzwzfyz 发表于 2022-9-22 09:12
方案:
1、程序中禁止用DELAY函数。理由:它占用CPU时间,影响其它程序运行。
2、显示的内容不要直接送LE ...

1、程序中禁止用DELAY函数。理由:它占用CPU时间,影响其它程序运行。

仅这一条就能把人吓傻
回复

使用道具 举报

5#
ID:1007932 发表于 2022-9-22 12:24 | 只看该作者
man1234567 发表于 2022-9-22 10:44
1、程序中禁止用DELAY函数。理由:它占用CPU时间,影响其它程序运行。

仅这一条就能把人吓傻

确实,51资源太少了,很多情况只能用delay,只能说尽量少用,比如用定时器定时读取刷新数据,再不然就时分多任务,但要额外占用资源,很多时候还不如用delay。
回复

使用道具 举报

6#
ID:1007932 发表于 2022-9-22 12:26 | 只看该作者
下一次显示时,上一次的位码或断码没有关闭。
回复

使用道具 举报

7#
ID:1034262 发表于 2022-9-22 14:29 | 只看该作者
扫描更新时,先输出位控无效,再装载段码,再允许位控。
回复

使用道具 举报

8#
ID:161164 发表于 2022-9-22 16:12 | 只看该作者
DS18B20的扫描时间太短了
每次扫描之间要留最少750ms来温度转换
时间不够,返回值有可能大于99
Nixie(6,T/10);这里T/10有可能大于18
NixieTable[T/10]就溢出了
回复

使用道具 举报

9#
ID:1045483 发表于 2022-9-22 17:26 | 只看该作者
感谢楼上各位大佬,问题已解决,是定时器中断会影响DS18B20的读取。在执行OneWire_Init(void)OneWire_SendBit(unsigned char Bit)时把定时器关了,执行完再打开定时器就可以解决残影闪烁的问题,也不影响其他功能。
再次感谢各位
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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