[51单片机] keil C51对unsigned long型支持是不是有bug?int就正常,long就黑屏

[复制链接]
938|13
 楼主 | 2018-7-11 17:44 | 显示全部楼层 |阅读模式
本帖最后由 rclong 于 2018-7-13 09:00 编辑

问题:数组越界,如3楼所说
解决方法:将数组SMG[7]定义为SMG[8].
感谢诸位.
====================================================
最近买了块TM1638方案的数码管+矩阵键盘,写了写代码准备搞和C51联调的培训.
结果在keil C51 uv5里遇到一个怪问题.
代码功能很简单,就是在数码管上显示0~99999999.
把这个整数存在变量number里,一开始用unsigned int型,OK没问题,到65535溢出归0,
改成unsigned long之后,编译也没有错误也没有警告,但是烧进去数码管就始终黑屏.
百思不得其解,还得请各位多多指点.

  1. //part04.以下是数码管显示,主要是尝试动态刷新数码管.
  2. //存在问题:number为unsigned long 型数据时代码不工作,调试后发现void number_display(unsigned int number)这一函数不工作,具体原因未知.2018年7月11日 15:04:36


  3. #include <reg52.h>

  4. //变量与表
  5. unsigned char code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x40,0xef,0x00};//共阴极数码管译码表.[18]为全熄灭.
  6. unsigned int number; //数字
  7. unsigned int timer_counter;        //时间计数标记.

  8. //引脚定义
  9. sbit        DIO=P2^0;
  10. sbit        CLK=P2^1;
  11. sbit        STB=P2^2;

  12. //函数声明
  13. void number_add(void);
  14. void number_display(unsigned int number);
  15. void led_segment_display(unsigned char ddata0,unsigned char ddata1,unsigned char ddata2,unsigned char ddata3,unsigned char ddata4,unsigned char ddata5,unsigned char ddata6,unsigned char ddata7);
  16. void Write_COM(unsigned char cmd);
  17. void TM1638_Write(unsigned char        DATA);

  18. //主函数
  19. void main(){
  20.         number = 0;
  21.         while(1){        
  22.                 number_add();
  23.                 number_display(number);
  24.         }
  25. }

  26. void number_add(void){
  27.         timer_counter = timer_counter + 1;        //通过引入timer_counter避免使用delay,从而对数码管动态扫描不构成影响.
  28.         if(timer_counter >= 50){         //调整该常量值可以调整number自加的速度.
  29.                 number = number + 199;
  30.                 if(number > 99999999)
  31.                         number = 0;
  32.                 timer_counter = 0;
  33.         }
  34.         else
  35.                 timer_counter = timer_counter + 1;
  36.         //P1 = 0xf0;
  37. }

  38. void number_display(unsigned int number)
  39. {
  40.         unsigned int temp_number;
  41.         unsigned char SMG[7],i;
  42.         char j;
  43.         unsigned int lowest_digit;        //最低位
  44.         temp_number = number; //整数拆分成各位
  45.         for(i=0;i<8;i++){
  46.                 lowest_digit = temp_number%10;//从低位往高位取
  47.                 temp_number = temp_number/10;
  48.                 SMG[i] = lowest_digit;
  49.         }
  50.         for(j=7;j>-1;j--){
  51.                 if(SMG[j]==0){
  52.                         SMG[j] = 18;
  53.                 }//从高位往低位看,高位为0的就赋18,只到第一个不为零的数出现.
  54.                 else
  55.                         j = -1;
  56.         }
  57.         led_segment_display(SMG[7],SMG[6],SMG[5],SMG[4],SMG[3],SMG[2],SMG[1],SMG[0]);
  58.         //P1 = 0x0f;
  59. }


  60. void led_segment_display(unsigned char ddata0,unsigned char ddata1,unsigned char ddata2,unsigned char ddata3,unsigned char ddata4,unsigned char ddata5,unsigned char ddata6,unsigned char ddata7){

  61.         unsigned char  writedata0,writedata1,writedata2,writedata3,writedata4,writedata5,writedata6,writedata7;
  62.         unsigned char  data0,data1,data2,data3,data4,data5,data6,data7;
  63.         
  64.         data0=ddata7;        //通过调整该部分代码即可调整数据对应数码管位置.
  65.         data1=ddata6;
  66.         data2=ddata5;
  67.         data3=ddata4;
  68.         data4=ddata3;
  69.         data5=ddata2;
  70.         data6=ddata1;
  71.         data7=ddata0;

  72.         writedata0=(tab[data0]&0x01)+((tab[data1]&0x01)<<1)+((tab[data2]&0x01)<<2)+((tab[data3]&0x01)<<3)+((tab[data4]&0x01)<<4)
  73.                 +((tab[data5]&0x01)<<5)+((tab[data6]&0x01)<<6)+((tab[data7]&0x01)<<7);

  74.         writedata1=((tab[data0]&0x02)>>1)+((tab[data1]&0x02))+((tab[data2]&0x02)<<1)+((tab[data3]&0x02)<<2)+((tab[data4]&0x02)<<3)
  75.                 +((tab[data5]&0x02)<<4)+((tab[data6]&0x02)<<5)+((tab[data7]&0x02)<<6);

  76.         writedata2=((tab[data0]&0x04)>>2)+((tab[data1]&0x04)>>1)+((tab[data2]&0x04))+((tab[data3]&0x04)<<1)+((tab[data4]&0x04)<<2)
  77.                 +((tab[data5]&0x04)<<3)+((tab[data6]&0x04)<<4)+((tab[data7]&0x04)<<5);

  78.         writedata3=((tab[data0]&0x08)>>3)+((tab[data1]&0x08)>>2)+((tab[data2]&0x08)>>1)+((tab[data3]&0x08))+((tab[data4]&0x08)<<1)
  79.                 +((tab[data5]&0x08)<<2)+((tab[data6]&0x08)<<3)+((tab[data7]&0x08)<<4);

  80.         writedata4=((tab[data0]&0x10)>>4)+((tab[data1]&0x10)>>3)+((tab[data2]&0x10)>>2)+((tab[data3]&0x10)>>1)+((tab[data4]&0x10))
  81.                 +((tab[data5]&0x10)<<1)+((tab[data6]&0x10)<<2)+((tab[data7]&0x10)<<3);

  82.         writedata5=((tab[data0]&0x20)>>5)+((tab[data1]&0x20)>>4)+((tab[data2]&0x20)>>3)+((tab[data3]&0x20)>>2)+((tab[data4]&0x20)>>1)
  83.                 +((tab[data5]&0x20))+((tab[data6]&0x20)<<1)+((tab[data7]&0x20)<<2);

  84.         writedata6=((tab[data0]&0x40)>>6)+((tab[data1]&0x40)>>5)+((tab[data2]&0x40)>>4)+((tab[data3]&0x40)>>3)+((tab[data4]&0x40)>>2)
  85.                 +((tab[data5]&0x40)>>1)+((tab[data6]&0x40))+((tab[data7]&0x40)<<1);

  86.         writedata7=((tab[data0]&0x80)>>7)+((tab[data1]&0x80)>>6)+((tab[data2]&0x80)>>5)+((tab[data3]&0x80)>>4)+((tab[data4]&0x80)>>3)
  87.                 +((tab[data5]&0x80)>>2)+((tab[data6]&0x80)>>1)+((tab[data7]&0x80));

  88.         Write_COM(0x8a);//亮度
  89.         Write_COM(0x40); //写 数据命令
  90.         STB=0;
  91.         TM1638_Write(0xc0);                //写地址命令
  92.         
  93.         TM1638_Write(writedata0);
  94.         TM1638_Write(0x80);
  95.         TM1638_Write(writedata1);
  96.         TM1638_Write(0x00);
  97.         TM1638_Write(writedata2);
  98.         TM1638_Write(0x00);
  99.         TM1638_Write(writedata3);
  100.         TM1638_Write(0x00);
  101.         TM1638_Write(writedata4);
  102.         TM1638_Write(0x00);
  103.         TM1638_Write(writedata5);
  104.         TM1638_Write(0x00);
  105.         TM1638_Write(writedata6);
  106.         TM1638_Write(0x00);
  107.         TM1638_Write(writedata7);
  108.         TM1638_Write(0x00);

  109.         STB=1;

  110. }

  111. void Write_COM(unsigned char cmd){                //发送命令字

  112.         STB=0;
  113.         TM1638_Write(cmd);
  114.         STB=1;
  115. }

  116. void TM1638_Write(unsigned char        DATA){                        //写数据函数
  117.         unsigned char i;
  118.         for(i=0;i<8;i++){
  119.                 CLK=0;
  120.                 if(DATA&0X01)
  121.                         DIO=1;
  122.                 else
  123.                         DIO=0;
  124.                 DATA>>=1;
  125.                 CLK=1;
  126.         }
  127. }



  128. //存在问题:number为unsigned long 型数据时代码不工作,调试后发现void number_display(unsigned int number)这一函数不工作,具体原因未知.2018年7月11日 15:04:29
  129. //part04.以上是数码管显示,主要是尝试动态刷新数码管.
复制代码
| 2018-7-11 18:30 | 显示全部楼层
    不支持64位的long,最高支持到32位,需要自己拆分64位
| 2018-7-11 22:17 | 显示全部楼层
unsigned char SMG[7]  改成  unsigned char SMG[8] 看看。
或者把int i和char j移动到 这个变量的前面定义。

可能是 SMG[7]=0;把i的值给覆盖了。

keil C51只支持32位的long int。最大到40亿左右。
| 2018-7-11 23:35 | 显示全部楼层
keil C51经常用long、unsigned long、float的路过,木发现过问题。

还是查查程序吧,不要轻易怀疑编译器。
| 2018-7-12 08:35 | 显示全部楼层
51里int是16位的,

先搞清楚基本情况再说吧
| 2018-7-12 08:41 | 显示全部楼层
别怀疑KEIL C51,肯定是程序的问题
| 2018-7-12 08:49 | 显示全部楼层
void led_segment_display(unsigned char ddata0,unsigned char ddata1,unsigned char ddata2,unsigned char ddata3,unsigned char ddata4,unsigned char ddata5,unsigned char ddata6,unsigned char ddata7)

这可是51呀,函数竟然带有8个变量...
 楼主 | 2018-7-12 10:43 | 显示全部楼层
ayb_ice 发表于 2018-7-12 08:35
51里int是16位的,

先搞清楚基本情况再说吧

int 16位这我知道
你想说的是什么呢?
 楼主 | 2018-7-12 10:48 | 显示全部楼层
雪山飞狐D 发表于 2018-7-11 18:30
不支持64位的long,最高支持到32位,需要自己拆分64位

我的意图是
比如number现在的值是12345678
12345678%10得8,将8放在SMG[7]里,这样数码管最后一位就显示8
然后number = number/10,也就是新number = 1234567
再对1234567%10,得SMG[6]显示为7
依次迭代就变成在数码管上显示1,2,3,4,5,6,7,8

number为unsigned int型时,代码工作很正常,从0到65535自动溢出归零都很正常
把几个变量改成unsigned long之后数码管就黑屏
也不知道为什么.
| 2018-7-12 10:59 | 显示全部楼层
rclong 发表于 2018-7-12 10:48
我的意图是
比如number现在的值是12345678
12345678%10得8,将8放在SMG[7]里,这样数码管最后一位就显示8

KEIL里面可以软件DEBUG的,你DEBUG一下就知道原因了。
| 2018-7-12 11:06 | 显示全部楼层
rclong 发表于 2018-7-12 10:48
我的意图是
比如number现在的值是12345678
12345678%10得8,将8放在SMG[7]里,这样数码管最后一位就显示8

SMG[7],却for循环了8次,你想干啥?内存都给你改写了。
| 2018-7-12 11:37 | 显示全部楼层
本帖最后由 ayb_ice 于 2018-7-12 11:38 编辑
rclong 发表于 2018-7-12 10:43
int 16位这我知道
你想说的是什么呢?

if(number > 99999999)
  •   for(i=0;i<8;i++){
  •                 lowest_digit = temp_number%10;//从低位往高位取
  •                 temp_number = temp_number/10;
  •                 SMG = lowest_digit;
  •         }



这些操作对于int明显不合适
| 2018-7-12 21:08 | 显示全部楼层
gx_huang 发表于 2018-7-12 11:06
SMG[7],却for循环了8次,你想干啥?内存都给你改写了。

是啊,我在三楼就指出这个bug了。
要改应该都改了,听他的意思是他就改了一个函数的一个参数。
| 2018-7-13 11:50 | 显示全部楼层
PCB打样 批量  8小时出货 焊接一条龙
3mil线  8mil孔 盲埋孔
阻抗 CAD图纸 半孔板 抄板 钢网
CEM-1 94VO 铝基板 FR4 FPC
单双面 5*5  40元 10片
单双面 10*10 50元 10片
四层   200元  10片
批量320元一平
板厚有 0.6  0.8 1.0 1.2 1.6 2.0 2.5 3.0MM
颜色 红 绿 白 黑 黄 紫
样品有铅无铅不加钱
批量可做24H加急 四层可做24H出货
QQ:2381329245(加Q私聊)
手机:139 2744 6192
网址:www.jhtcpcb.com
欢迎各位砸单!
暂时不需要也没关系 留个联系方式 以备不时之需!!!
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

关闭

热门推荐上一条 /4 下一条

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