乐高 发表于 2025-1-19 10:12:52

神农鼎 发表于 2025-1-19 09:16
《8051U深度入门到32位51大型实战视频》,【免费 + 包邮 送】实验箱@Ai8051U,100万套 - TinyML,Ai8051U...

这一段只详细讲了功能2:在数码管上显示4字节长整型数;功能1没有展开讲,只是一笔带过。

乐高 发表于 2025-1-20 14:59:08

第11集矩阵按键课后小练
简易洗衣机面板
1.按下开机键后,数码管显示1,表示默认为清洗模式1;
2.用矩阵按键模拟洗衣机的操作面板,前五个按键模拟1-5的清洗模式按键,选择几的时候数码管显示数字几,表示以当前为第几个功能;
3.按下启动后,按照选择的模式对应的时间开始倒计时,倒计时结束后,数码管熄灭,表示清洗完成(清洗时间自己随意设置)。
因为手头没有合适的矩阵键盘所以今天现焊了一块4 x 4的矩阵键盘。
1-5键设置了模式参数,16键设置为启动键。6-15键没设置,为空键。
矩阵键盘接口为P2口。数码管显示采用HC595驱动的8位数码管,但只驱动了末后两位。程序在冲哥的第11集DEMO程序的基础上稍作了一些增减。
下面为矩阵键盘扫描程序
void KEY_Task(void)                           //4*4矩阵键盘扫描
{//#define key P2                                        //矩阵键盘的数据口为P2
      u8 key_temp;
         u8 key1,key2;
         key=0xf0;
      key1=key;
      if(key1 != 0xf0 )
      {
                key1=key&0xf0;                        //确定哪一行的按键按下      
                key=0x0f;
                key2=key;
                if(key2 != 0x0f )
                        key2=key&0x0f;                  //确定哪一列的按键按下
                key_temp=key1|key2;                  //确定按键位置
    }
//      else
//                key_temp = no_key ;
      switch(key_temp)                //当确定按键按下后,列举所有的按键情况
      {
               case 0xee: key_value=0;break;
               case 0xde: key_value=1;break;
               case 0xbe: key_value=2;break;
               case 0x7e: key_value=3;break;
               case 0xed: key_value=4;break;
               case 0xdd: key_value=5;break;
               case 0xbd: key_value=6;break;
               case 0x7d: key_value=7;break;
               case 0xeb: key_value=8;break;
               case 0xdb: key_value=9;break;
               case 0xbb: key_value=10;break;
               case 0x7b: key_value=11;break;
               case 0xe7: key_value=12;break;
               case 0xd7: key_value=13;break;
               case 0xb7: key_value=14;break;
               case 0x77: key_value=15;break;
                // case 0xff: key_value=16;break;                        
      }
      switch(key_value)
      {
                case 0: fen = 10;break;                              //赋予1-5各按键所表示模式运行时间
                case 1: fen = 11;break;
                case 2: fen = 12;break;
                case 3: fen = 13;break;
                case 4: fen = 14;break;
                case 15: start = 1;break;                        //第16键设置为启动工作键
      }
}数码管显示程序:
u8 SEG_NUM[]=          //数码管段码数组
{
    0x3F,       /*'0', 0*/
    0x06,       /*'1', 1*/
    0x5B,       /*'2', 2*/
    0x4F,       /*'3', 3*/
    0x66,       /*'4', 4*/
    0x6D,       /*'5', 5*/
    0x7D,       /*'6', 6*/
    0x07,       /*'7', 7*/
    0x7F,       /*'8', 8*/
    0x6F,       /*'9', 9*/
    0x77,       /*'A', 10*/
    0x7C,       /*'B', 11*/
    0x39,       /*'C', 12*/
    0x5E,       /*'D', 13*/
    0x79,       /*'E', 14*/
    0x71,       /*'F', 15*/
    0x40,       /*'-', 16*/
    0x00,       /*' ', 17*/
    0x80,       /*'.', 18*/
};
void Seg_Task(void)
{
      if(key_value != 15)                                                                   //按任意一个模式选择键,回到等待启动状态
                start = 0;
      if(start)                                                                                 //启动工作后数码管显示倒计时时间,否则显示模式编号
                num = fen;      
      else
         num = key_value+1;                                           //+1      为默认模式号为1                              
      
      
      if( Seg_no ==0 )                                                               
      {
                if(num%10==0&&num/10==0)                                                //如果十位和个位都为0,则消隐
                        Display_Seg( SEG_NUM , ~T_NUM);               
                else
                        Display_Seg( SEG_NUM , ~T_NUM);      //显示个位数字
      }
      else if( Seg_no ==1 )                                                      
      {
                if(num/10==0)                                                                        //如果十位为0,则消隐
                        Display_Seg( SEG_NUM , ~T_NUM);
                else
                        Display_Seg( SEG_NUM , ~T_NUM);               
      }      
      else
      {      }
      Seg_no ++;
      if( Seg_no>1 )
                Seg_no=0;
}ISP软件端虚拟数码管显示程序:
void SEG_PC( void )                              //只显示末两位
{
      u8 cod;      

      cod = SEG_NUM;                                       
      cod = SEG_NUM;
      cod =SEG_NUM;                                                

      cod = SEG_NUM;                                          
      cod = SEG_NUM;
      cod = SEG_NUM;                                                      
    if(num/10==0)                                        //如果十位为0,则消隐
                cod = SEG_NUM;               
      else
                cod = SEG_NUM;      
      if(num/10==0 && num%10==0)                //如果十位和个位都为0,则消隐
                cod = SEG_NUM;
      else
            cod = SEG_NUM;
      
      SEG7_ShowCode(cod);
}放上完整演示视频
530




乐高 发表于 2025-1-21 09:58:01

第十一集矩阵键盘   任意端口组合矩阵键盘数据口
前面的矩阵键盘接口程序用了一个完整的8位P2口,这样编写程序比较简单明了。如果矩阵键盘接的不在一个口上,就不能用前面的程序了,需要加以处理才能使用。
如果矩阵键盘8个接口如下
sbit COL1 =      P2^0;                        //矩阵键盘的数据口端口定义
sbit COL2 =      P2^1;
sbit COL3 =      P2^2;                        
sbit COL4 =      P2^3;
sbit ROW1 =      P5^7;
sbit ROW2 =      P5^6;
sbit ROW3 =      P3^7;
sbit ROW4 =      P3^6;需要使用如下的代码进行处理
//矩阵端口数据处理,逐位放入对应的IO口
void Matrixkey_W(u8 m)            //向8个管脚写入数据
{
      COL1 = m & (0x01<<0);
      COL2 = m & (0x01<<1);
      COL3 = m & (0x01<<2);
      COL4 = m & (0x01<<3);
      ROW1 = m & (0x01<<4);
      ROW2 = m & (0x01<<5);
      ROW3 = m & (0x01<<6);
      ROW4 = m & (0x01<<7);
}
u8 Matrixkey_R()                                 //从8个管脚读出数据
{
u8 n;
   n&= (u8)COL1;
// if(COL1)   //这个地方有个疑问,如用了这两行代码,程序跑起来就不正常,      
//   n |= 0x01;                                       //改用上一条代码,程序就正常,真是奇了怪了!
   if(COL2)
         n |= 0x02;
   if(COL3)
      n|= 0x04;
   if(COL4)
         n |= 0x08;
   if(ROW1)
         n |= 0x10;
   if(ROW2)
         n |= 0x20;
   if(ROW3)
         n |= 0x40;
   if(ROW4)
         n |= 0x80;
   return n;
}void KEY_Task(void)                                                            //4*4矩阵键盘扫描
{
        u8 key_temp;
        u8 key1,key2;
        Matrixkey_W(0xf0);
        key1 = Matrixkey_R();
        if(key1 != 0xf0 )
        {
                key1 = Matrixkey_R()&0xf0;                                  //确定哪一行的按键按下       
                Matrixkey_W(0x0f);
                key2 = Matrixkey_R();
                if(key2 != 0x0f)
                        key2 = Matrixkey_R()&0x0f;                  //确定哪一列的按键按下
                key_temp=key1|key2;                                  //确定按键位置
               
    }

        switch(key_temp)                                              //当确定按键按下后,列举所有的按键情况
        {
               case 0xee: key_value=0;break;
               case 0xde: key_value=1;break;
               case 0xbe: key_value=2;break;
               case 0x7e: key_value=3;break;
               case 0xed: key_value=4;break;
               case 0xdd: key_value=5;break;
               case 0xbd: key_value=6;break;
               case 0x7d: key_value=7;break;
               case 0xeb: key_value=8;break;
               case 0xdb: key_value=9;break;
               case 0xbb: key_value=10;break;
               case 0x7b: key_value=11;break;
               case 0xe7: key_value=12;break;
               case 0xd7: key_value=13;break;
               case 0xb7: key_value=14;break;
               case 0x77: key_value=15;break;
               
                // case 0xff: key_value=16;break;                       
        }
        switch(key_value)
        {
                case 0: fen = 10;break;                                //赋予1-5各按键所表示模式运行时间
                case 1: fen = 11;break;
                case 2: fen = 12;break;
                case 3: fen = 13;break;
                case 4: fen = 14;break;
                case 15: start = 1;break;                        //第16键设置为启动工作键
        }

}
其他代码不变,还是沿用前面附件里的程序。




芯征程 发表于 2025-1-21 11:40:59

感谢您的支持与任何,今天给您免费包邮送AI8051U实验箱,期待您更多的测评

电子DIY小家 发表于 2025-1-21 12:04:03

乐高 发表于 2025-1-19 08:44
有一个问题想请教一下:
STC_ISP 调试仿真接口下面的调试接口协议中,7段数码管接口的功能1:




和printf用法一样的,只是要考虑数码管不能显示一些特殊的字符和汉字等等,只要能显示的字符和数字就能直接当printf这么用~!


乐高 发表于 2025-1-21 12:19:20

电子DIY小家 发表于 2025-1-21 12:04
和printf用法一样的,只是要考虑数码管不能显示一些特殊的字符和汉字等等,只要能显示的字符和数字就能 ...

谢谢版主的回复,现在明白了!

乐高 发表于 2025-1-21 14:08:31

第13楼   矩阵键盘   任意端口组合矩阵键盘数据口

程序的疑问已经解决。只要在Matrixkey_R()函数内定义n的时候预赋值为0就可以了。不是说好的定义默认值为0的吗?
u8 Matrixkey_R()                               //从8个管脚读出数据
{
u8 n =0;
// n&= (u8)COL1;这条语句就不用了
   if(COL1)                                                       
       n |= 0x01;                                       
   if(COL2)
       n |= 0x02;
   if(COL3)
        n|= 0x04;
   if(COL4)
       n |= 0x08;
   if(ROW1)
       n |= 0x10;
   if(ROW2)
       n |= 0x20;
   if(ROW3)
       n |= 0x40;
   if(ROW4)
       n |= 0x80;
   return n;
}


乐高 发表于 2025-1-22 14:04:20

第12集 复位系统 课后小练


这一课的课后小练是在第10课的基础上加了看门狗复位,开机LOGO,以及按键复位。
密码从“12345678”改为“12345670”,便于实验箱2x4矩阵键盘输入。
由于马上要回老家过年了,时间太仓促,程序没有整理。没有做完硬件矩阵按键数码管和虚拟键盘数码管共同操作的程序。
以后有时间再慢慢修改,完善。
534

乐高 发表于 2025-1-28 20:30:55

第十三集   外部中断

#include "ai8051u.h"
#include "stc32_stc8_usb.h"
#include "intrins.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void Delay20ms(void);
void main()
{
    P_SW2 |= 0x80;                                                                  //外设端口切换寄存器,P_SW2第7位EAXFR置一使能访问XFR
    CKCON = 0x00;
                WTST = 0x00;
          P0M1 = 0x00;   P0M0 = 0x00;
    P1M1 = 0x00;   P1M0 = 0x00;
    P2M1 = 0x00;   P2M0 = 0x00;
    P3M1 = 0x00;   P3M0 = 0x00;
    P4M1 = 0x00;   P4M0 = 0x00;                           
    P5M1 = 0x00;   P5M0 = 0x00;
    P6M1 = 0x00;   P6M0 = 0x00;
    P7M1 = 0x00;   P7M0 = 0x00;
    usb_init();                                     //USB CDC 接口配置   
    IE2 |= 0x80;                                    //使能USB中断
                IT1 = 1;                                                                                                                                                                //使能INT1下降沿中断
          EX1 = 1;                                                                                                                                                                //使能INT1中断
          EA = 1;
                P40 = 0;
    P06=0;               
    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置
    while (1)
    {
      if (bUsbOutReady)
      {
         USB_SendData(UsbOutBuffer,OutNumber);    //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            
            usb_OUT_done();
      }
               
   if(P01==0)
               {
                              Delay20ms();
                        if(P01==0)
                                        P00 = 0;
                              while(P01==0);                                 
               }                        
         }
}

void INT1_Isr() interrupt 2
{
P00 = 1;
}
void Delay20ms(void)      //@24.000MHz
{
      unsigned long edata i;

      _nop_();
      _nop_();
      i = 119998UL;
      while (i) i--;
}581


乐高 发表于 2025-1-28 20:50:38

第十四集IO中断

void common_isr() interrupt 37
{
        u8 intf;
        intf = P0INTF;
        if(intf)
        {
                P0INTF = 0x00;
                if(intf & 0x02)
                {key_num = 1;P0INTE = 0x00;
                P07 = !P07;
                }
                if(intf & 0x04)
                {key_num = 2;P0INTE = 0x00;}
                if(intf & 0x08)
                {key_num = 3;P0INTE = 0x00;}
        }
}
578
页: 1 [2] 3 4 5 6
查看完整版本: AI8051U教学视频课后小练 | 高质量打卡