乐高 发表于 2025-1-15 18:31:26

AI8051U教学视频课后小练 | 高质量打卡

第一集 序言

两天前收到了“擎天柱”转接板,很漂亮。


STC的产品越来越强大了!技术支持也越来越全面。激发出了同学们的学习热情
   Ai32位8051
8 0 5 1凌绝顶,核心算力在哪里 !
算力一日同风起,扶摇直上九万里 !
百兆硬件真浮点,三角函数运算器 !
神州春色三万里,封神榜永远是你 !
===老骥伏枥志在万里,来我们再战三万里



乐高 发表于 2025-1-15 18:41:35

第三集 点亮第一颗LED
咱也从点亮第一颗LED开始吧。
522


乐高 发表于 2025-1-15 22:52:28

第四集 USB不停电下载

AI8051U的USB不停电下载冲哥已经在视频里讲的很清楚了,同学们只要按部就班地一步步照抄就能顺利实现。
但8位U芯片不停电下载这次没有讲,以前有没有讲我不清楚,以前的课我只听了一点点。我手上正好有一片自制的STC8H8K64U核心板

本来是一直用串口下载程序的,这次正好借机学习一下,也加个不停电下载程序。
原以为很简单,照搬就行,但过程说明不是完全照搬,自己摸索肯定也不会成功,后面看到了神***的贴子,才把问题解决了。
有两个关键点看图,其他的都问题不大。


编译后有4K多代码,8K以下芯片只能量力而行。

下载成功后,ISP下载接口显示“USB-CDC,CDC”
523



乐高 发表于 2025-1-16 09:51:44

第六集 IO输入输出
这一集的课后小练题目是:
1,按一下P32按钮灯亮,按一下P33按钮灯灭;
2,按一下亮一颗灯,再按一下亮两颗灯,直到全亮。
第一个题目相对简单,我把两题要求做在一起了。用移位法比较直接,也可以用pow()幂函数来实现。
//按一下第1个灯亮,再按一下第2个灯亮,再按一下第3个灯亮......一直到8个灯全亮,再按一下从头再来                        
                if( P32 == 0 )                                                                //判断P32按钮是否按下
                {
                        Delay20ms();                                                      //延时20ms消抖
                        if( P32 == 0 )
                        {      
                        //以下用移位法来实现此功能      
                              if(temp==0)                              
                              {
                                        temp = 1;
                                        temp =~temp;
                              }
                              else
                                        temp <<= 1;
                                 P2 = temp;      
                                        while( P32 == 0 );                                        //等待P32松开                              
                        }
                } //按一下第1个灯亮,再按一下第2个灯亮,再按一下第3个灯亮......一直到8个灯全亮,再按一下从头再来                        
                if( P32 == 0 )                                                                //判断P32按钮是否按下
                {
                        Delay20ms();                                                      //延时20ms消抖
                        if( P32 == 0 )
                        {      
                        //以下用幂函数来实现
                              if(i<8)
                              {
                                        num = pow(2,i)+num;      //用幂函数实现各位依次置一
                                        i++;
                              }
                              else
                              {      
                                        i = 0;
                                        num = 0;                                       
                              }
                              P2 = ~num;
                        //      printf("num: %x",num);
                              while( P32 == 0 );                                        //等待P32松开                              
                        }                        
                }
                        题目对于关灯的要求不多,我就自我发挥一点,当有多灯点亮后,按P33用移位法逐位熄灭。
//按一下依次灯灭
                if( P33 == 0 )                                                                //判断P33按钮是否按下
                {
                        Delay20ms();                                                      //延时20ms消抖
                        if( P33 == 0 )
                        {                              
                              temp =~P2;
                if(temp)                              
                              {
                                        temp >>= 1;
                                    P2 =~temp;
                              }
                              else
                                  P2 = 0xff;
                              while( P33 == 0 );                                        //等待P33松开                              
                        }
                }      524

乐高 发表于 2025-1-16 17:00:58

第七集-定时器配套程序 课后小练 电子功德箱:
1.按下按键1,串口显示“双倍功德时间”,再次按下显示“单倍功德时间”;
2.按下按键2,双倍功德时间下串口显示“功德+2 当前功德:xxx”;
3.按下按键2,单倍功德时间下串口显示“功德+1 当前功德:xxx”;
4.功德+1时,LED点亮1秒后熄灭表示功德成功点亮;
5.功德+2时,LED点亮2秒后熄灭表示功德成功点亮;
先上视频525
while(1)
      {                        
                //按下按钮1,串口显示“双倍功德时间”,再次按下显示“单倍功德时间”,再次按下不断切换
                if( P32 == 0 )                                                                //判断P32按钮是否按下
                {
                        Delay20ms();                                                      //延时20ms消抖
                        if( P32 == 0 )
                        {
                              Ds_State = !Ds_State;                              //单双切换
                              
                              if( Ds_State )                                        //Ds_State=1,为双
                                        printf("双倍功德时间\r\n");

                              else                                                                //Ds_State=0,为单
                                        printf("单倍功德时间\r\n");

                              while( P32 == 0 );                                        //等待P32松开
                              
                        }
                }
                if( P33 == 0 )                                                                //判断P33按钮是否按下
                {
                        Delay20ms();                                                      //延时20ms消抖
                        if( P33 == 0 )
                        {
                              if( Ds_State )                                                               
                              {
                                        count =count+2;
                                        printf("功德+2 当前功德:%d\r\n",(int)count);
                                        P20 =0;
                                        TR0 = 1;                              //定时器0开始计时
                                        //Timer0_Init();
                              }
                              else
                              {
                                        count =count+1;
                                        printf("功德+1 当前功德:%d\r\n",(int)count);
                                        P20 =0;
                                        TR0 = 1;                              //定时器0开始计时
                                        //Timer0_Init();
                              }
                              while( P33 == 0 );                                        //等待P32松开                              
                        }
                }               
      }这里说一下这个视频是怎么来的:下载了一个“一维科技”的EV虚拟摄像头,手机端和电脑端都安装这款软件,然后无线连接。
视频是用windows11系统自带的截图工具录制的。第一次这么操作,做的很粗糙。

乐高 发表于 2025-1-17 12:34:50

第九集 数码管课后小练
简易10秒免单计数器
1. 在前四位数码管上显示目标时间,即“10.00”表示定时时间10秒。
2. 后四位显示当前的计时00.00,最小单位为10ms。
3. 按下开始按钮后,每10ms最末尾的数字+1;直到按下结束按钮后停止计数。
4. 后四位数码管显示当前时间,如果时间正好是停在了10.00,就可以免单。
还是先上视频,视频中的八位数码管是我手工焊出来的。
526
程序在冲哥DEMO 的基础上稍作修改:
主程序:
while(1)
      {               
      if (bUsbOutReady)                                                      //如果接收到了数据
      {
          //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
                        
            usb_OUT_done();                                                      //
      }
                Task_Pro_Handler_Callback();                              //执行功能函数
               
                if(P32==0)                                                          //P32为开始按钮,按下时间清零,计时开始
                {                                                                                        //在io.h头文件中声明下面3个全局变量
                        shihaomiao = 0;                                                      //extern u8 shihaomiao;
                        miao = 0;                                                                //extern u8 miao;
                        start = 1;                                                               //externbit start;
               }
                if(P33==0)                                                                        //P33为结束按钮,按下计时停止
               {
                  start = 0;
                  }
         }
}
io.c文件:
u8 shihaomiao =0;
u8 miao =0;
bit start = 0;
void Seg_Task(void)
{
      u8 num = 0;
      if( Seg_no ==0 )                                                                //秒十位
      {
                Display_Seg( SEG_NUM , ~T_NUM);                //数码管刷段码和位码
      }
      else if( Seg_no ==1 )                                                      //秒个位
      {
                Display_Seg( SEG_NUM+0x80 , ~T_NUM);      //+0x80,是为了加入DP点显示
      }      
      else if( Seg_no ==2 )                                                      //百毫秒
      {
                Display_Seg( SEG_NUM , ~T_NUM);                //数码管刷段码和位码
      }      
      else if( Seg_no ==3 )                                                      //十毫秒
      {
                Display_Seg( SEG_NUM , ~T_NUM);                //数码管刷段码和位码
      }
      else if( Seg_no ==4 )//秒十位
      {
                num = miao/10;
                Display_Seg( SEG_NUM , ~T_NUM);                //数码管刷段码和位码
      }      
      else if( Seg_no ==5 )//秒个位
      {
                num = miao%10;
                Display_Seg( SEG_NUM+0x80 , ~T_NUM);//+0x80,是为了加入DP点显示
      }      
      else if( Seg_no ==6 )//百毫秒
      {
                num = shihaomiao/10;
                Display_Seg( SEG_NUM , ~T_NUM);                //数码管刷段码和位码
      }
      else if( Seg_no ==7 )//十毫秒
      {
                num = shihaomiao%10;
                Display_Seg( SEG_NUM , ~T_NUM);                //数码管刷段码和位码
      }      
      else
      {
               
      }
      Seg_no ++;
      if( Seg_no>7 )
                Seg_no=0;
}
void TIMECOUNT_Task(void)
{
      if(start)
         shihaomiao ++;
      if( shihaomiao>99 )
      {
                shihaomiao = 0;
                miao++;
                if( miao>59 )
                {
                        miao = 0;
                }
      }
}task.c文件:
static TASK_COMPONENTS Task_Comps[]=
{
//状态计数周期函数
      
// {0, 300,   300,   LED0_Blink},      /* task 1 Period: 300ms */
// {0, 600,   600,   LED1_Blink},      /* task 1 Period: 600ms */
// {0, 900,   900,   LED2_Blink},      /* task 1 Period: 600ms */
// {0, 10,    10,    KEY_Task},      /* task 1 Period: 600ms */
{0,    1 ,1   ,   Seg_Task},      /* task 1 Period: 600ms */
{0,10,10,   TIMECOUNT_Task},   /* task 1 Period: 10ms   此处修改为10 */ 其余不变。

乐高 发表于 2025-1-17 22:24:19

加油!加油!加油!

乐高 发表于 2025-1-18 22:07:06

第十集 虚拟LED数码管课后小练

密码锁
1. 没有输入时,显示“- - - - - - - -”
2. 有输入时,按下一个按键,开始按顺序写入
   例如,第一个按下1,显示“1 - - - - - - - ”
   例如,第二个按下3,显示“1 3 - - - - - - ”
3. 当按下的密码为“1 2 3 4 5 6 7 8”时,数码管显示open的字符,否则,还是显示“- - - - - - - -”
题目要求比较简洁,考虑到如果前面几位按错了,不想8位全部按完就重新开始按,这种情况比较常见。
所以我增加了这部分的功能。下面还是先上视频。
529
main程序内先定义3个全局变量:

extern u32 REC_NUM;
extern u8 j , open ;

在config.h内调用头文件:    #include "string.h"   //memcmp()、memcpy()两函数需要。
while(1)
        {
               
      if (bUsbOutReady)                                                        //如果接收到了数据
      {
            if( UsbOutBuffer==106)               //加入恢复起始状态的按键“*”,键值为106
                        {
                                open = 0;
                                j = 0;
                        }
                        else
                        {
                                REC_NUM = UsbOutBuffer-48;       //把接收到的数字减48为需要的数值
                          j++;
                       }       
            usb_OUT_done();                                                        //
      }
                Task_Pro_Handler_Callback();                                //执行功能函数
        }#include "io.h"

u8 State1 = 0;                                        //LED1初始状态
u8 State2 = 0;                                        //LED2初始状态
u8 State3 = 0;                                        //LED3初始状态

u16 Key_Vol ;                                //按键按下持续时间
BYTE cod0[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};                               //数码管初始值显示“--------”
BYTE cod[] ={0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};                                      //cod[]保存输入的数字               
BYTE cod1[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,0x7F,0x6F,0x40};   // 0-9 段码数组
BYTE cod2[] = {0x06, 0x5B, 0x4F, 0x66, 0x6D ,0x7D, 0x07, 0x7F};                                      // 密码数字
BYTE cod3[] = {0x40, 0x40, 0x5c, 0x73, 0x79, 0x54, 0x40, 0x40};                                       //“--OPEN--”
u32 REC_NUM = 10;      //起始值数码管显示“-”
u8 j =0;
u8 open =0;
void TASK_1(void)
{
        if((open ==0)&&(j==0))//起始状态
                memcpy(cod,cod0,8);       //将初始值cod0复制给cod,回到起始状态
        if(open ==0)    //open=0 闭锁状态,open=1 开锁状态
        {
                cod = cod1;               //把收到的数字逐一存入cod[]中
                if(j==8)                                               //如果按了8个数字
                {
                        if(!memcmp(cod,cod2,8))      //比较cod与cod2两数组是否相等,若相等显示“--OPEN--”,不等显示初始值“--------”
                        {
                                open = 1;
                        }
                else
                        {
                                memcpy(cod,cod0,8);       //将初始值cod0复制给cod,回到起始状态
                                SEG7_ShowCode(cod);                  //显示初始值“--------”
                                j = 0;
                        }
                }       
          else                
                SEG7_ShowCode(cod); //显示输入的数字
        }       
        else
        {
                SEG7_ShowCode(cod3);//显示“--OPEN--”
                memcpy(cod ,cod0,8);                           //将数组cod0的值复制给cod,等待下一次解锁
                j = 0;
        }       
}
程序在冲哥第十课程序的基础上,稍作以上修改,其余不用动。

乐高 发表于 2025-1-19 08:44:48


有一个问题想请教一下:
STC_ISP 调试仿真接口下面的调试接口协议中,7段数码管接口的功能1:

在数码管上显示字符串,我研究了半天也没搞清楚,冲哥在课程里面也没有讲这一部分,
有没有哪位大神给解释一下?

神农鼎 发表于 2025-1-19 09:16:06



《8051U深度入门到32位51大型实战视频》,【免费 + 包邮 送】实验箱@Ai8051U,100万套 - TinyML,Ai8051U 人工智能 开山之作,AI手写计算器 国芯技术交流网站 - AI32位8051交流社区
页: [1] 2 3 4 5 6
查看完整版本: AI8051U教学视频课后小练 | 高质量打卡