找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4103|回复: 2
收起左侧

函数为什么shownumber里面 i 只能定义signed char 型,而不能使无符号型

[复制链接]
ID:225339 发表于 2017-9-12 19:01 | 显示全部楼层 |阅读模式
/*加法器
一1先取键值(去抖动在中断,数码管显示在中断(读取缓存器))
二键值的处理在主函数
三处理的结果十六进制转十进制,并存入缓存器*/
#include <reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit keyin1  = P2^4;
sbit keyin2  = P2^5;
sbit keyin3  = P2^6;
sbit keyin4  = P2^7;
sbit keyout1 = P2^3;
sbit keyout2 = P2^2;
sbit keyout3 = P2^1;
sbit keyout4 = P2^0;

unsigned char code ledchar[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};

unsigned char ledbuf[6]={0xff,0xff,0xff,0xff,0xff,0xff};          //16进制转10金之后的计算后的结果送入这个缓存器  P0直接读取这个用于显示


/*矩阵按键到标准键盘的映射变 ASCLL表查询可知*/
unsigned char code keycodemap[4][4]={
                                                                {0x31,0x32,0x33,0x26},        //1  2   3   向上
                                                                {0x34,0x35,0x36,0x25},        //4  5   6   向左
                                                                {0x37,0x38,0x39,0x28},        //7  8   9   向下
                                                                {0x30,0x1B,0x0D,0x27},        //0 ESC 回车 向右
                                                        };

unsigned char keystate[4][4]={{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};      //16个按键的当前键值   1代表的是这个按键是按下还是松开          最好用BIT 但是数组不允许


void keydrive();

void keyaction(unsigned char keycode);

void shownumber(unsigned long number);


void keydrive();
void ledscan();            //数码管显示函数
void keyscan();     //按键扫描函数

void main()
{
        TMOD=0x01;                  //用定时器T0模式1
        TH0=0XFC;                                   //定时以为时间12/11059200,需要定时0.001S  需要
        TL0=0X66;
        EA=1;
        ET0=1;
        TR0=1;
        ADDR3=1;
        ENLED=0;
        ledbuf[0]=ledchar[0];
   /*按键当前状态刷出来后 取键值 */
   while(1)
   {
         keydrive();
   }
}


void shownumber(unsigned long num)
{       
         signed char i;                                /这里为什么不能用 unsigned char
        unsigned char buf[6];  //待显示的数字
        for(i=0;i<6;i++)        //将数取出来放入数组
        {
                buf[i]=num%10;
                num=num/10;
        }
        for(i=5;i>=1;i--)
        {
                if(buf[i]==0x00)      //从最高位起,遇到0转换为空格,遇到非0则退出循环
                {
                        ledbuf[i]=0xff;
                }
                else
                {
                         break;
                }
        }                                            //剩余低位都如实转换为数码管显示字符
        for(;i>=0;i--)
        {
                ledbuf[i]=ledchar[buf[i]];
        }
}


void keyaction(unsigned char keycode)
{
        static unsigned long  addend=0;   //中间值
        static unsigned long result=0;  //结果值
        if((keycode>=0x30)&&(keycode<=0x39))  {addend=((addend*10)+(keycode-0x30));shownumber(addend);}
        else if(keycode == 0x26)          {result=(addend+result);addend=0; shownumber(result);}                                         // +
        else if(keycode == 0x0D)          {result=(addend+result);addend=0; shownumber(result);}                                    //回车
        else if(keycode == 0x1B)          {result=0;addend=0; shownumber(addend);}                                        //ESC
}


/*将按键(根据位置)取出来的值,根据映射表提取值,并且进行运算*/
void keydrive()
{
        unsigned char i,j;
        static unsigned char backup[4][4]={{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};      //16个按键的上一个状态
   for(i=0;i<4;i++)
   {
                           for(j=0;j<4;j++)
                        {
                                if( keystate[i][j]!=backup[i][j])          //按键有动作
                                {
                                        if(backup[i][j]!=0)                      //按键处于松开状态
                                        {
                                        keyaction(keycodemap[i][j]);
                                        }
                                        backup[i][j]=keystate[i][j];       
                                }
                        }            
   }
}


void ledscan()                 //数码管扫描函数
{
        static unsigned char i=0;
     /*下面用处数码管的显示,读取缓存ledbuf的值*/
         P0=0xff;                        //消影
         switch(i)                                //进一次中断刷新一位
         {
         case 0: ADDR0=0; ADDR1=0; ADDR2=0; P0=ledbuf[0];i++;break;
         case 1: ADDR0=1; ADDR1=0; ADDR2=0; P0=ledbuf[1];i++;break;
         case 2: ADDR0=0; ADDR1=1; ADDR2=0; P0=ledbuf[2];i++;break;
         case 3: ADDR0=1; ADDR1=1; ADDR2=0; P0=ledbuf[3];i++;break;
         case 4: ADDR0=0; ADDR1=0; ADDR2=1; P0=ledbuf[4];i++;break;
         case 5: ADDR0=1; ADDR1=0; ADDR2=1; P0=ledbuf[5];i=0;break;
         default: break;
         }
}


void keyscan()     //按键扫描函数
{
        unsigned char i;
        static  unsigned char keyout=0 ;  //行索引
        static  unsigned char  keytemp[4][4]={{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};

        keytemp[keyout][0]=(keytemp[keyout][0]<<1)|keyin1; //扫完16个按键的第一位需要4MS 扫完8位需要32MS   
        keytemp[keyout][1]=(keytemp[keyout][1]<<1)|keyin2; //一个按键每隔4MS扫一次
        keytemp[keyout][2]=(keytemp[keyout][2]<<1)|keyin3; // 8个状态是32MS之间的稳态值
        keytemp[keyout][3]=(keytemp[keyout][3]<<1)|keyin4; //每进中断一次(1MS)扫描一行  
        for(i=0;i<4;i++)
        {
                if(( keytemp[keyout][i]&0x0f) == 0x00 )     {keystate[keyout][i]=0;}
                else if( ( keytemp[keyout][i]&0x0f) == 0x0f )   {keystate[keyout][i]=1;}    //扫描结果的赋值       
        }
        keyout++;  //下一次扫描下一行
        keyout=keyout&0x03;    //逢三复位

        /*读取列值 行首先要置位0  为什么把置位放在后面 ? 1如果放在中断扫描前
        马上就能扫描 而行的置位是需要一定时间的,就会导致列值不准确  2 如果放在后面
        其实是给下一次行扫描的置位,经过了主程序的延迟 ,置位完成,程序才足够强壮*/
        switch(keyout)
        {
                case 0: keyout4=1; keyout1=0; break;
                case 1: keyout1=1; keyout2=0; break;
                case 2: keyout2=1; keyout3=0; break;
                case 3: keyout3=1; keyout4=0; break;
                default: break;       
        }
}
void time0() interrupt 1                 //中断中 行要置位0
{
           TH0=0XFC;                                   //定时以为时间12/11059200,需要定时0.001S  需要
        TL0=0X66;
        ledscan();
        keyscan();
}

回复

使用道具 举报

ID:89515 发表于 2017-9-12 20:48 | 显示全部楼层
可以用,如果要用到负值就不能用
回复

使用道具 举报

ID:225339 发表于 2017-9-13 19:06 | 显示全部楼层
恩 我知道了 i变到-1了 所以不行了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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