wuzhengmin 发表于 6 天前

// ----------------------- p10端口闪烁        -----------------------       
        if( P10_STATE == 0 )
                LED40_SetBit(1,0);
        else
                LED40_ClrBit(1,0);
       
        P10_STATE = !P10_STATE;
}


闪烁就是在高低电平切换,最容易实现的


wuzhengmin 发表于 6 天前

再来看我们下面虚拟的数码管:


wuzhengmin 发表于 6 天前

任务2:左边数码管显示P32按下次数
右边数码管显示P33按下次数

这个要学会按键按下次数的计算......

其实还是用常整数可能会比字符串更方便
u32 KEY_Count = 0;
// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数void TASK_2( void ){        KEY_Count = KEY1_COUNT *10000 + KEY2_COUNT;                SEG7_ShowLong( KEY_Count ,10);        }

这个不好理解,有压缩饼干的味道..........

当然,要从这里入手:


u16 KEY1_COUNT = 0;                //P32按钮计数
u16 KEY2_COUNT = 0;                //P33按钮计数

void KEY_Task(void)
{
// ------------P32按钮计数------------       
        if( P32 == 0 )
        {
                Key_Vol++;
                if( Key_Vol==5 )
                {
                        KEY1_COUNT++;
                }
        }
        else
        {
                Key_Vol = 0;
        }
       
// ------------P33按钮计数------------               
        if( P33 == 0 )
        {
                Key_Vol_2++;
                if( Key_Vol_2==5 )
                {
                        KEY2_COUNT++;
                }
        }
        else
        {
                Key_Vol_2 = 0;
        }       
       
}




wuzhengmin 发表于 5 天前

又遇到一个奇诡的问题:


下载的时候,ISP打开编译好的 .HEX文件的时候,说文件大学超出范围:

wuzhengmin 发表于 5 天前

还有个小问题:

这里原来是乘以10000


void TASK_2( void )
{
        KEY_Count = KEY1_COUNT *10000 + KEY2_COUNT;//2个次数整合为1个方便显示
       
        SEG7_ShowLong( KEY_Count ,10);
       
}


实验后,发现改成1000,效果更好:


void TASK_2( void )
{
        KEY_Count = KEY1_COUNT *1000 + KEY2_COUNT;//2个次数整合为1个方便显示
       
        SEG7_ShowLong( KEY_Count ,10);
       
}

可以解决P32按10次后乱码的问题,当然也不是彻底解决......


wuzhengmin 发表于 5 天前

u16 KEY1_COUNT = 0;                //P32按钮计数
u16 KEY2_COUNT = 0;                //P33按钮计数

本来2个按键起码按65534次才出问题,但是实际上按了20多次就胡乱显示啦


P33就问题不大,主要是在P32上:

确实是65535溢出问题!

//signed long KEY_Count = 0;
//float KEY_Count = 0;
u32 KEY_Count = 0;
// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数
void TASK_2( void )
{
        KEY_Count = KEY1_COUNT *1000 + KEY2_COUNT;//2个次数整合为1个方便显示
        //printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);

          SEG7_ShowLong( KEY_Count ,10);
          //SEG7_ShowFloat(KEY_Count);
}


我直觉问题是在显示上,本来想看看printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);
KEY_Count超过65534之后是多大?

但是 USB-CDC串口不知道从ai8051u哪里发出的打印指令一直在回打:

只能先放一下,暂时*1000 ,这样P33可以按999次,P32最大按64次!




wuzhengmin 发表于 5 天前

当然,我发现还有


int SEG7_ShowString(const char *fmt, ...); 函数


去手册看看?

手册指引我们去:
上面调试仿真接口函数的详细帮助信息请参考下载软件中的“接口协议及帮助”



功能2:在数码管上显示4字节长整型数
命令格式:37H 53H 45H 47H 4CH x1 x2 00H d1 d2 d3 d4
命令说明:
第1~4字节:命令头
第5字节:功能选择(4CH显示长整型数)
第6字节:数据存储格式(0:LE, 1:BE)
第7字节:显示进制(02H:二进制, 0AH:十进制, 10H:十六进制)
第8字节:保留
第9~12字节:长整型数的存储数据
示例1:发送37H 53H 45H 47H 4CH 00H 10H 00H 12H 34H 56H 78H
在数码管上会显示78564312
示例2:发送37H 53H 45H 47H 4CH 01H 10H 00H 12H 34H 56H 78H
在数码管上会显示12345678
库函数声明:void SEG7_ShowLong(long n, char radix);//n:长整型数 radix:进制
库函数调用:SEG7_ShowLong(0x98765432, 16);
注:当超出显示范围时自动转为科学计数法进行显示


本来应该是对的,4字节长整型是可以正常显示的。但是:


//signed long KEY_Count = 0;
//float KEY_Count = 0;
//u32 KEY_Count = 0;
long KEY_Count = 0;

// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数
void TASK_2( void )
{
        KEY_Count = KEY1_COUNT *100 + KEY2_COUNT;//2个次数整合为1个方便显示
        //printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);

          SEG7_ShowLong((long) KEY_Count ,10);
          //SEG7_ShowFloat(KEY_Count);
}


4字节长整型如何正确定义?u32不行么unsigned long KEY_Count = 0; u32 KEY_Count = 0;


应该都没问题啊?反正一超出65534就乱了,根源应该是计数器溢出中断?

65536代表的是一个16位计数器的最大值。这个计数器由高8位(TH0)和低8位(TL0)组成,可以存储2^16=65536个数。当计数器从65536开始计数时,经过一段时间后会溢出并产生中断。


所以根本问题不是显示!

我们验证一下:


//signed long KEY_Count = 0;
//float KEY_Count = 0;
//u32 KEY_Count = 0;
unsigned long KEY_Count = 0;

// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数
void TASK_2( void )
{
        KEY_Count = KEY1_COUNT *100 + KEY2_COUNT;//2个次数整合为1个方便显示
        //printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);
                KEY_Count = 88888888;
          SEG7_ShowLong((long) KEY_Count ,10);
          //SEG7_ShowFloat(KEY_Count);
}








wuzhengmin 发表于 5 天前

当然,实际上65535也是够用的


我们乘以100

这是P32可以按655次,P33反正可以进位,就算不进位也有99次,混过去是可以的...........

wuzhengmin 发表于 5 天前

最后就是拟键盘!


任务3:按下数字按键在数码管显示对应的按键数字!
例:按下按键0数码管显示0;

先学会用extern 关键字:

extern u32 REC_NUM;//变量是在io.c建立的
//这个变量要在其他函数使用,就要加extern
//关键字,并且这里不能赋值,就是不能这样:
//extern u32 REC_NUM=0;只能extern u32 REC_NUM;
//意思是我已经在别的地方定义好了。加了extern
//编译器就会自动去别的地方找到这个变量

看看主函数:

void main(void)
{
        Sys_init();                                                                                //系统初始化
        usb_init();                                     //USB CDC 接口配置

    IE2 |= 0x80;                                    //使能USB中断
        Timer0_Init();                                                                        //定时器初始化
    EA = 1;                                                                                        //IE |= 0X80;
       
        P40 = 0;
       
        while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置
       
        while(1)
        {
               
      if (bUsbOutReady)                                                        //如果接收到了数据
      {
                        REC_NUM = UsbOutBuffer-48;
                        //我们接受的数据在UsbOutBuffer里面
/*功能:在虚拟键盘上按键然后发送相应的键值到设备
命令格式:4EHH 59H 50H 00H x1 00H 00H
命令说明:
?
第1~4字节:命令头
第5字节:保留
第6字节:按键键值
第7~8字节:保留
我们需要第6个字节(从0数是第5个)
UsbOutBuffer-48;-48就是ASCII编码问题,我们
要直接显示数字,不需要显示ASCII编码
上位机发0的编码48过来,我们直接发0回去显示
用void TASK_3( void )完成任务
示例:接收到4BH 45H 59H 50H 00H 30H 00H 00H
表示数字键0被按下*/
                       
         // USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
                       
            usb_OUT_done();                                                        //
      }
                Task_Pro_Handler_Callback();                                //执行功能函数

        }
}


u32 REC_NUM是在io.c里定义赋初值的,顺便写好任务3函数void TASK_3( void )



u32 REC_NUM = 0;

// 任务3:按下数字按键在数码管显示对应的按键数字!
void TASK_3( void )
{
        SEG7_ShowLong( REC_NUM ,10);
}





wuzhengmin 发表于 5 天前

课后练习,好像很难

不过,我们已经学完了十集,还算可以啦,没有间断,一鼓作气就算合格


今天到此为止啦
页: 5 6 7 8 9 10 11 12 13 14 [15] 16 17
查看完整版本: 第一次:环境的创立 | 送实验箱