打印
[51单片机]

keil C51对unsigned long型支持是不是有bug?int就正常,long就黑屏

[复制链接]
4975|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
rclong|  楼主 | 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之后,编译也没有错误也没有警告,但是烧进去数码管就始终黑屏.
百思不得其解,还得请各位多多指点.

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


#include <reg52.h>

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

//引脚定义
sbit        DIO=P2^0;
sbit        CLK=P2^1;
sbit        STB=P2^2;

//函数声明
void number_add(void);
void number_display(unsigned int number);
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);
void Write_COM(unsigned char cmd);
void TM1638_Write(unsigned char        DATA);

//主函数
void main(){
        number = 0;
        while(1){        
                number_add();
                number_display(number);
        }
}

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

void number_display(unsigned int number)
{
        unsigned int temp_number;
        unsigned char SMG[7],i;
        char j;
        unsigned int lowest_digit;        //最低位
        temp_number = number; //整数拆分成各位
        for(i=0;i<8;i++){
                lowest_digit = temp_number%10;//从低位往高位取
                temp_number = temp_number/10;
                SMG[i] = lowest_digit;
        }
        for(j=7;j>-1;j--){
                if(SMG[j]==0){
                        SMG[j] = 18;
                }//从高位往低位看,高位为0的就赋18,只到第一个不为零的数出现.
                else
                        j = -1;
        }
        led_segment_display(SMG[7],SMG[6],SMG[5],SMG[4],SMG[3],SMG[2],SMG[1],SMG[0]);
        //P1 = 0x0f;
}


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){

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

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

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

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

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

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

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

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

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

        Write_COM(0x8a);//亮度
        Write_COM(0x40); //写 数据命令
        STB=0;
        TM1638_Write(0xc0);                //写地址命令
        
        TM1638_Write(writedata0);
        TM1638_Write(0x80);
        TM1638_Write(writedata1);
        TM1638_Write(0x00);
        TM1638_Write(writedata2);
        TM1638_Write(0x00);
        TM1638_Write(writedata3);
        TM1638_Write(0x00);
        TM1638_Write(writedata4);
        TM1638_Write(0x00);
        TM1638_Write(writedata5);
        TM1638_Write(0x00);
        TM1638_Write(writedata6);
        TM1638_Write(0x00);
        TM1638_Write(writedata7);
        TM1638_Write(0x00);

        STB=1;

}

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

        STB=0;
        TM1638_Write(cmd);
        STB=1;
}

void TM1638_Write(unsigned char        DATA){                        //写数据函数
        unsigned char i;
        for(i=0;i<8;i++){
                CLK=0;
                if(DATA&0X01)
                        DIO=1;
                else
                        DIO=0;
                DATA>>=1;
                CLK=1;
        }
}



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

相关帖子

沙发
雪山飞狐D| | 2018-7-11 18:30 | 只看该作者
    不支持64位的long,最高支持到32位,需要自己拆分64位

使用特权

评论回复
板凳
linqing171| | 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亿左右。

使用特权

评论回复
地板
coody| | 2018-7-11 23:35 | 只看该作者
keil C51经常用long、unsigned long、float的路过,木发现过问题。

还是查查程序吧,不要轻易怀疑编译器。

使用特权

评论回复
5
ayb_ice| | 2018-7-12 08:35 | 只看该作者
51里int是16位的,

先搞清楚基本情况再说吧

使用特权

评论回复
6
gx_huang| | 2018-7-12 08:41 | 只看该作者
别怀疑KEIL C51,肯定是程序的问题

使用特权

评论回复
7
l4157| | 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个变量...

使用特权

评论回复
8
rclong|  楼主 | 2018-7-12 10:43 | 只看该作者
ayb_ice 发表于 2018-7-12 08:35
51里int是16位的,

先搞清楚基本情况再说吧

int 16位这我知道
你想说的是什么呢?

使用特权

评论回复
9
rclong|  楼主 | 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之后数码管就黑屏
也不知道为什么.

使用特权

评论回复
10
gx_huang| | 2018-7-12 10:59 | 只看该作者
rclong 发表于 2018-7-12 10:48
我的意图是
比如number现在的值是12345678
12345678%10得8,将8放在SMG[7]里,这样数码管最后一位就显示8

KEIL里面可以软件DEBUG的,你DEBUG一下就知道原因了。

使用特权

评论回复
11
gx_huang| | 2018-7-12 11:06 | 只看该作者
rclong 发表于 2018-7-12 10:48
我的意图是
比如number现在的值是12345678
12345678%10得8,将8放在SMG[7]里,这样数码管最后一位就显示8

SMG[7],却for循环了8次,你想干啥?内存都给你改写了。

使用特权

评论回复
12
ayb_ice| | 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明显不合适

使用特权

评论回复
13
linqing171| | 2018-7-12 21:08 | 只看该作者
gx_huang 发表于 2018-7-12 11:06
SMG[7],却for循环了8次,你想干啥?内存都给你改写了。

是啊,我在三楼就指出这个bug了。
要改应该都改了,听他的意思是他就改了一个函数的一个参数。

使用特权

评论回复
14
约会吧| | 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
欢迎各位砸单!
暂时不需要也没关系 留个联系方式 以备不时之需!!!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

575

帖子

0

粉丝