找回密码
 立即注册
楼主: dyx811

《8051U深度入门到32位51大型实战教学视频》学习记录

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-1-1 11:42:02 | 显示全部楼层
第十集 虚拟LED数码管 的学习记录
       通过AIapp-isp软件中的“仿真调试接口”找到接口协议及帮助,可以找到适合使用的各种虚拟设备驱动函数。
1.    利用擎天柱转换板,向PC发送数据,用AIapp_isp软件中的仿真调试功能,虚拟擎天柱的各个IO端口。
通过DIP40—led界面展示出来。
库函数声明: void LED40_SendData(BYTE *dat, BYTE size);
库函数调用:
BYTEcod[8];
cod[0] =0x0f;         //第6字节:P0~P5端口用0屏蔽(bit0:P0, bit1:P1, bit2:P2,bit3:P3,bit4:P4,...)
cod[1] =0x12;        //bit0:P0发送的数据(8位)
cod[2] =0x34;        //bit2:P0发送的数据(8位)
cod[3] =0x56;        //bit3:P0发送的数据(8位)
cod[4] =0x78;        //bit4:P0发送的数据(8位)
LED40_SendData(cod, 5);//“cod”指针数组,“5”里面包含5个对应内容字节的数据。
2.    虚拟数码管。虚拟一个8位的数码管
可以调用4个函数实现不同显示效果,常用的是直接显示段码
库函数调用:
BYTE cod[8];//定义一个数组
cod[0] = 0x3f;
cod[1] = 0x06;
cod[2] = 0x5b;
cod[3] = 0x4f;
cod[4] = 0x66;
cod[5] = 0x6d;
cod[6] = 0x7d;
cod[7] = 0x27;
SEG7_ShowCode(cod);//调用发送函数
3.    虚拟键盘。虚拟一个多功能键盘,向单片机发送指令和数据,接收处理并回传到USB调试接口,用虚拟的8位数码管显示出来。
一切都是虚拟,所以需要将这个函数规定的键值按照规律翻译,才能正确显示出来,视频教学里面采用“-48”,巧妙的同步的一致的显示在虚拟的数码管上。
冲哥非常厉害!
虚拟键盘直接以串行的方式发送出来,需要在“UsbOutBuffer[5]”提取。
if (bUsbOutReady)                            //如果接收到了数据
        {
            REC_NUM = UsbOutBuffer[5];            //验证“UsbOutBuffer[5]”只有PC发送了数据才会更新,无新数据不会变。
                                            //放在了缓存里。
            //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            
            usb_OUT_done();                            //
        }
4.    课后练习:8位密码锁
-1.没有输入时,显示“- - - - - - - -”
-2.有输入时,按下一个按键,开始按顺序写入
    例如,第一个按下1,显示“1 - - - - - - -”   
    例如,第二个按下3,显示“1 3 - - - - - -”
-3.当按下的密码为“ 1 2 3 4 5 6 7 8”时,数码管显示open的字符,否则,还是显示“- - - - - - - -”
/*     课后任务8位密码锁
-1.没有输入时,显示“- - - - - -- -”
-2.有输入时,按下一个按键,开始按顺序写入
        例如,第一个按下1,显示“1 - - - - - - -”   
        例如,第二个按下3,显示“1 3 - - - - - -”
-3.当按下的密码为“ 1 2 3 4 5 67 8”时,数码管显示open的字符,否则,还是显示“- -- - - - - -”
*/
下面是实现该功能的部分程序,数码管段码数组用软件生成,放在SEG_NUM[19]数组里。
模拟当中出现的问题是,第8位显示不出来,直接跳转到“open”。里面还需要加延时语句。暂时不加。
还有就是开机显示“--------”部分,模拟的时候来不及显示,只有按出错了就显示了。哈哈,这单片机运行速度太快了!PC反应不过来。
u8 Step =0;
u8REC_NUM = 0xff;
u8 stop =0;
voidTASK_5( void )//任务五
{
u8 i ;
u8 cod[8];      //新的函数(数组)里面需包含关键字“cod”
if(stop == 0)         //开机显示“--------”,只运行一次。如果要一直显示可以直接取消stop标志判断。持续发送。
{
        for(i=0;i<8;i++)
        {
               cod = SEG_NUM[19];
        }
        SEG7_ShowCode(cod); //
        stop = 1;
}
if(REC_NUM != 0xff) //有新数据
{
        switch(Step)
        {            
               case 0:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第1位的段码
               case 1:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第2位的段码
               case 2:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第3位的段码
               case 3:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第4位的段码
               case 4:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第5位的段码
               case 5:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第6位的段码
               case 6:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第7位的段码
               case 7:cod[Step]=SEG_NUM[REC_NUM];break;       //装入第8位的段码
               default:break;
        }
        REC_NUM = 0xff;//清空缓存
        SEG7_ShowCode(cod);
        Step++;
        if(Step ==8)
        {
         if((cod[0]==SEG_NUM[1])&&(cod[1]==SEG_NUM[2])&&(cod[2]==SEG_NUM[3])&&(cod[3]==SEG_NUM[4])&&
                (cod[4]==SEG_NUM[5])&&(cod[5]==SEG_NUM[6])&&(cod[6]==SEG_NUM[7])&&(cod[7]==SEG_NUM[8]))
               {
                      cod[0] = SEG_NUM[20];       //第1位显示的段码
                      cod[1] = SEG_NUM[20];       //第2位显示的段码
                      cod[2] = SEG_NUM[20];       //第3位显示的段码
                      cod[3] = SEG_NUM[20];       //第4位显示的段码
                      cod[4] = SEG_NUM[17];       //第5位显示的段码
                      cod[5] = SEG_NUM[18];       //第6位显示的段码
                      cod[6] = SEG_NUM[14];       //第7位显示的段码
                      cod[7] = SEG_NUM[16];       //第8位显示的段码
               }
               else//输入错误
               {
                      for(i=0;i<8;i++)
                      {
                             cod =SEG_NUM[19];
                      }
                      Step = 0;
               }
        }
        SEG7_ShowCode(cod);        //函数里必须包含调用的发送函数
}
}  
1.png
2.png
3.png      
                              
今天是2025年的1月1号。记录我的学习历程。
跟着冲哥学,学到了好多知识!感谢冲哥!感谢国芯!
2025,新的一年,祝愿大家新年快乐!收获满满!

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-1-2 11:49:50 | 显示全部楼层

夸奖了,就学习的时候认真了点,分享+记录!一起加油哦!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-1-6 01:56:26 | 显示全部楼层
第十一集 矩阵按键 的学习记录
1.    矩阵按键的原理:(IO口设置为准双向口,2行4列用6个IO可得到8个按键,4行4列可得到16个按键)
a.    首先让列都输出低电平,如4列;让行输出高电平,如2行
b.    判断行是否有低电平出现,若有表示有按键按下。
c.    让每行赋值低电平,每列赋值高电平(翻转)。再检测那列出现低电平,就可以判断是这个低电平对应列的按键按下了。
2.     矩阵按键的程序实现:由矩阵按键得到键值,同时依然需要按键消抖处理后,才用于程序实施!保证触发精确。
3.     用按键密码锁任务验证矩阵按键,这次是用了试验箱上面的数码管,就需要略作修改,调用的595驱动函数,就实现了。
4.     课后任务:简易洗衣机面板
a按下开机键后,数码管显示1,表示默认为清洗模式1;
b用矩阵按键模拟洗衣机的操作面板,前五个按键模拟1-5的清洗模式按键,选择几的时候数码管显示数字几,表示以当前为第几个功能;
c按下启动后,按照选择的模式对应的时间开始倒计时,倒计时结束后,数码管熄灭,表示清洗完成。
d.下面是逻辑处理和显示部分,按键扫描和任务调度依然采用冲哥的多任务处理框架。显示部分非常耗费存储空间,代码还需要优化。
voidTime_Count_Decrement(void) //秒计数,减计数,
{
       if(Run_Pause == 1)       //1.启动,2.暂停,0.模式切换
       {
              Run_Time--;  //
              if(Run_Time == 0)
              {
                     Run_ON = 0 ;
                     Run_Pause = 0;
              }
       }
}
voidSeg_Task(void) //显示函数
{
       static       u8i=0;
       if(Run_ON == 1)
       {
              if(Run_Pause == 1) //1.启动,2.暂停,0.模式切换
              {
                     switch(i)
                     {
                            case 0 :
                                   {
                                          Display_Seg(SEG_NUM[Run_Time/10] , T_NUM[1]);
                                   }
                                   break;
                            case 1 :
                                   {
                                          Display_Seg(SEG_NUM[Run_Time%10] , T_NUM[0]);
                                   }
                                   break;
                     }
                     i++;
                     if(i>1)
                     {
                            i=0;
                     }            
              }            
              else if(Run_Pause == 0) //0.仅开机时的模式切换,1.启动,2.暂停
              {      
                     switch(Display_data)
                     {
                            case 0 :
                                   {
                                          Display_Seg(SEG_NUM[1] , T_NUM[0]);//仅仅在数码管1显示1
                                   }
                                   break;
                            case 1 :
                                   {
                                          Display_Seg(SEG_NUM[1] , T_NUM[0]);//仅仅在数码管1显示1
                                   }
                                   break;
                            case 2 :
                                   {
                                          Display_Seg(SEG_NUM[2] , T_NUM[0]);//仅仅在数码管1显示2
                                   }
                                   break;
                            case 3 :
                                   {
                                          Display_Seg(SEG_NUM[3] , T_NUM[0]);//仅仅在数码管1显示3
                                   }
                                   break;
                            case 4 :
                                   {
                                          Display_Seg(SEG_NUM[4] , T_NUM[0]);//仅仅在数码管1显示4
                                   }
                                   break;
                            case 5 :
                                   {
                                          Display_Seg(SEG_NUM[5] , T_NUM[0]);//仅仅在数码管1显示5
                                   }
                                   break;                          
                     }
              }
       }
       else
       {
              for(i=0;i<8;i++)
              {
                     Display_Seg( SEG_NUM[17] ,T_NUM);//关机状态,清空。
              }
       }
}      
voidLaundry_Task(void)//洗衣机程序
{      
       switch(Key_Sec)//调用键值进行处理
       {
              case 1 :
                     {
                            Run_ON = !Run_ON ;//开关机
                            if(Run_ON == 0)
                            {
                                   Run_Pause = 0;//关机状态下,所有模式清空
                                   Display_data= 1 ;
                            }
                     }
                     break;
              case 2 :
                     {
                            if(Run_ON == 1)
                            {
                                   Run_Pause +=1 ;//启动暂停键模式切换
                                   if(Run_Pause>2)
                                   {
                                          Run_Pause= 1;
                                   }
                            }      
                     }      
                     break;
              case 3 :
                     {
                            Display_data = 1;//显示数据1内容
                            Run_Time =Time_mode[0];//装入设定值1
                     }
                     break;
              case 4 :
                     {
                            Display_data = 2;//显示数据2内容
                            Run_Time =Time_mode[1];//装入设定值2
                     }
                     break;
              case 5 :
                     {
                            Display_data = 3;//显示数据3内容
                            Run_Time =Time_mode[2];//装入设定值3
                     }
                     break;
              case 6 :
                     {
                            Display_data = 4;//显示数据4内容
                            Run_Time =Time_mode[3];//装入设定值4
                     }
                     break;
              case 7 :
                     {
                            Display_data = 5;//显示数据5内容
                            Run_Time =Time_mode[4];//装入设定值5
                     }
                     break;     
       }
       Key_Sec = 0;
}


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-1-13 21:46:19 | 显示全部楼层
第十二集复位系统 的 学习记录
1.   复位系统:系统上电复位都是开始工作的第一步。上电复位,使整个系统处于或回到默认的初始硬件状态下,复位也就是强制单片机进行初始化,作用是使CPU和系统中的其他部件都处于一个确定的初始状态,并从这个状态开始工作。
2.   复位在Ai8051U中 包含了上电复位、低压复位、复位脚复位和看门狗复位。也可统称为硬件复位或者软件复位两大类。
3.   硬件复位:a.上电复位,通过引脚上的接入的一个按钮和阻容元件达到复位效果。复位电压达到(1.7~1.9V)可正常复位
b.注意,Ai8051U的复位引脚可以通过程序初始化得到想要的复位效果。默认它的复位引脚没有开启,需要在“AIapp-ISP”的“硬件选项”中开启复位功能。该引脚为“P47”。
C.“AIapp-ISP”中与复位相关的设置,“上电复位使用较长延时”:内核决定,可以让各个硬件都完成初始化,但有开机时间要求的可以不开启这个功能。“允许低压复位”:指VCC电压低于设定值时产生复位。“下次冷启动时,P32/P33为0时才可下载程序”“复位脚用作IO口”等设置,让IO口具有更多的功能。
d.看门狗复位:这是需要对看门狗控制寄存器进行相应的设置才能正常使用。寄存器“WDT_CONTR”开启后,达到设定值
  后,将会使单片机复位。所以就必须让单片机定期的去清空计数单元,防止复位。如果单片机异常,不能有效清除计数单元的值,则看门狗认为系统死机,复位动作。WDT_CONTR=0x2n即可开启(n为8级分频系数),WDT_CONTR=0x3n清空定时器,防止复位,同时赋值n。
4.   软件复位:对寄存器“IAP-CONTR”赋值达到复位效果。(IAP控制寄存器)
IAP-CONTR=0x60(复位到系统ISP区,进入下载模式
IAP-CONTR=0x28(复位到用户系统区)
IAP-CONTR=0x20复位到用户程序区)
5.   课后任务:密码锁
a.没有输入时,显示“-- - - - - - -”
b.有输入时,按下一个按键,开始按顺序写入
    例如,第一个按下1,显示“1 - - - - - - -”   
    例如,第二个按下3,显示“1 3 - - - - - -”
c.当按下的密码为“ 12 3 4 5 6 7 0”时,数码管显示open的字符,否则,还是显示“- - - - - - - -”
新增:
e.看门狗,超时1秒自动复位
f.增加开机版本号,开机显示三秒的U 1.00 版本号
g.增加手动复位,P33按钮按下时重启(方便查看版本号和清除密码)
新增代码:
主函数中:
void main(void)
               WDT_CONTR= 0X25;                          //开启看门狗定时器@24M≈1秒定时时长
              
主循环中:
while(1)
      WDT_CONTR= 0X35;            //清除看门狗定时器,且赋值@24M≈1秒定时时长
       按键任务中:
KEY_Task
       IAP_CONTR = 0X20;         //按下后,复位到用户程序区
       调度任务中:
              Task_Display_Control();//1000毫秒执行一次
{
                     if(!System_control)   //该函数执行完就失效。
                     {
                            Key_Vol= 0; //清空按键计数器
                            Key_Vol3= 0;//清空按键计数器
                            if(++Display_Control==3)   
                            {
                                   passward[0]= 19; //装入正常数据     “--------”
                                   passward[1]= 19;     //该数组在初始化时的数据为“U1.00”
                                   passward[2]= 19;
                                   passward[3]= 19;
                                   passward[4]= 19;
                                   passward[5]= 19;
                                   passward[6]= 19;
                                   passward[7]= 19;
                                   System_control= 1;
              }
       }
}
虽然用另外的一个定时器也能达到效果,且可以关闭,但消耗容量比新增几个变量来运算还多。这个还是比较好的。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-1-31 21:54:00 | 显示全部楼层
第十三集外部中断 的 学习记录
1.   关于中断,是专为CPU处理紧急事件而设置的实时处理功能。
2.   CPU总是会响应优先级别最高的中断请求处理;
3.   CPU能暂停处理中断源的服务程序,转而处理优先级更高的中断请求,执行完后,再回到原低级的中断服务程序;
4.   部分中断的优先级可以用软件设置,高优先级的中断请求可以打断低优先级的中断;
5.   每个中断源可以用软件独立的控制开中断或者关闭中断。
中断优先级结构图.png
6.   从上往下,中断优先级越来越低
7.   外部中断,就是单片机的引脚引入的一个信号,如高低电平的变化,就会让内部程序暂时打断,转而去执行相应的处理程序,处理完后又回到原来中断的地方继续执行原来的程序。
8.   外部中断引脚,须包含INTx标识的才具有该功能,同时还需注意他们支持什么电平变化的触发,如(上升沿触发、下降沿触发等),具体可以查看手册。
9.   结构示意途中,可以看出,如:要使用外部中断0,需要设置相关控制寄存器-> IT0(上升\下降沿选择)、IE0(触发标志)、EX0(开启外部中断0)、EA(开启总中断)
       2025-01-31_202107.png
10. 中断函数的编写。一般分为初始化,即配置相关寄存器,如设置触发信号的来源(什么类型),设置触发信号的形式(高低电平),设置开启命令(打开相关通道);然后确认相关的中断端口号,编写进入中断后需要执行的程序。
初始化配置只需要令相关寄存器到对应状态的指令即可;
中断服务程序的编写需要确认正确的端口号(用关键字“interrupt+数字编号”的形式来表达)后,为该服务程序取个好听好记的名字+中断服务号的格式,像编写正常函数一样来编写需要执行的程序。
       11.课后练习。用矩阵键盘打开LED,用外部中断1控制LED关闭。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-2-2 12:20:51 | 显示全部楼层
第十四集 IO中断 的 学习记录
1.   Ai8051u支持普通IO口中断,优先级为4,每一个IO口都可以单独拎出来设置,非常强大!
2.   普通IO口的配置:
2025-02-02_113716.png
                              
3.   用作中断的IO口配置:
2025-02-02_114513.png
4.   配置中断IO的同时,还需要配置其相关的控制寄存器:
2025-02-02_114813.png
2025-02-02_114851.png
2025-02-02_114910.png
2025-02-02_115330.png
2025-02-02_115412.png
配置完,才能使用“普通IO口的中断功能”。
5.   课程重点讲解如何配置中断优先级,以实现不同的功能,虽然最后一个实验,冲哥将P4设置为最高优先级,同时又将定时器T0也改为最高优先级,我感觉最高优先级始终偏向于P4,他们似乎都是同时在执行,但效果确也实现了。看来还需要加强学习!
6.   课后小练:多路抢答器。
上电后一位数码管显示0,3个按钮任意一个按下就显示该按钮序号。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-02 02:49:44
已绑定手机

4

主题

64

回帖

762

积分

高级会员

积分
762
发表于 2025-2-7 12:37:05 | 显示全部楼层
第十五集 定时器做计数器 的 学习记录

1.        单片机的定时器可以配置做为计数器使用,一般引脚标识上包含字符T、INT等。
2.        配置定时器工作模式的相关寄存器有TMOD,中断请求寄存器TCON。
               配置为外部计数TI_CT=1;配置计数模式;配置控制寄存器GATE和TR;配置计数值;配置输入脚位打开上拉电阻。
3.        配置为计数器初始化时,可以用位寻址的方式配置(TMOD支持位寻址,利用软件查找功能,可以定位到有关“TMOD”的相关头文件),如配置TMOD寄存器中的TI_CT=1,则表示配置TI定时器为外部计数模式;同时需要配置其中的        T1_MO、T1_M1寄存器,从4种组合模式中选择一种来设定其数据计数方式。用位寻址的方式配置简洁明了,当然也可以用直接配置寄存器的方式,用整体赋值,不需要记,但需要查手册算。如“TMOD &= 0x08”。
4.        课程中验证了对引脚低电平出现次数的记录并打印出来,和引脚出现低电平持续时间的累计计数并打印出来。非常的引人入胜。需要反复观看,才能体会老师讲解的精髓!
5.        关于计数器应用的课后小练:计算两次按键按下的时间间隔,同时累计按键按下的次数,数码管左边显示次数,右边显示前后间隔时间。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:102
  • 最近打卡:2025-05-02 08:26:36
已绑定手机

2

主题

67

回帖

606

积分

高级会员

积分
606
发表于 2025-4-11 14:10:01 | 显示全部楼层
做好笔记学习深刻
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 20:40 , Processed in 0.169236 second(s), 93 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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