skyalong 发表于 2025-6-5 09:33:29

第十集 虚拟键盘LED和数码管
虚拟显示——LED      
任务1:P2口流水灯,P10闪烁
任务1代码
void Task1(void)
{
    u8 cod[8] = {0};
   
    cod[0] = 0x3f;//指定端口 xx11 1111 xxP5P4 P3P2P1P0
    cod[1] = 0xff;//P0 0000 0001
    cod[2] = (led_num % 2)|0xfe;//P1 0000 0010
    cod[3] = ~SEG_W;//P2 0000 0100
    cod[4] = 0xff;//P3 0101 0101
    cod[5] = 0xff;//P4 1010 1010
    cod[6] = 0xff;//P5 0101 0101
    LED40_SendData(cod, 7);
    led_num ++;
    if(led_num > 7)led_num = 0;
}

虚拟显示——数码管
   
任务2:左边数码管显示P32按下次数,右边数码管显示P33按下次数
任务2代码(做了修改,第4位加点显示做分割,默认显示0000.0000)
u8 key_num1 = 0;
u8 K32num = 0,K33num = 0;
void Task2(void)
{
    u8 cod[8];
    cod[0] = SEG_D/1000%10];
    cod[1] = SEG_D/100%10];
    cod[2] = SEG_D/10%10];
    cod[3] = (SEG_D%10])|0x80;
    cod[4] = SEG_D/1000%10];
    cod[5] = SEG_D/100%10];
    cod[6] = SEG_D/10%10];
    cod[7] = SEG_D%10];
    SEG7_ShowCode(cod);
    if(P32 == 0)
    {
      key_num++;
      if(key_num == 5)
      {
            K32num++;
      }   
    }else{key_num = 0;}
    if(P33 == 0)
    {
      key_num1++;
      if(key_num1 == 5)
      {
            K33num++;
      }   
    }else{key_num1 = 0;}
}

虚拟键盘

任务3:按下数字按键在数码管显示对
应的按键数字!
例:按下按键0数码管显示0;
任务3代码
void main(void)
{   
    Sys_init();
    usb_init();                                     //USB CDC 接口配置
    set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
   
    Init_595();
    Timer0_Init();
    EA = 1;
    while(1)
    {   
      Task_Pro_Handler_Callback();
      REC_NUM = UsbOutBuffer[5]-48;
    }
}
u16 REC_NUM = 0;
void Task3(void)
{
    SEG7_ShowLong(REC_NUM,10);
}

拓展代码
u8 cod = {16,16,16,16,16,16,16,16};
u8 cod1 ;
void Task3(void)
{      
      if(seg_num == 0)
      {
                cod = 0x40;
                cod = 0x40;
                cod = 0x40;
                cod = 0x40;
                cod = 0x40;
                cod = 0x40;
                cod = 0x40;
                cod = 0x40;
      }      
      cod = SEG_D;
      cod1 = REC_NUM;


      SEG7_ShowCode(cod);
      if(seg_num >= 8)
      {
                if(cod1 == 1&&cod1 == 2&&cod1 == 3&&cod1 == 4&&cod1 == 5&&cod1 == 6&&cod1 == 7&&cod1 == 8)
                {
                        cod = 0x40;
                        cod = 0x40;
                        cod = 0x5c;//o
                        cod = 0x73;//p
                        cod = 0x79;//e
                        cod = 0x54;//n
                        cod = 0x40;
                        cod = 0x40;               
                        
                        SEG7_ShowCode(cod);
                }else seg_num = 0;//8位结束回0
      }
      
}
工程代码

拓展代码工程














--哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前






skyalong 发表于 2025-6-10 23:25:27

第十一集 矩阵按键
摘要1.矩阵按键的原理2.矩阵按键的程序实现原理    任务1代码
u8 key_board_num = 0xff;
void key_board(void)
{
COL1 = 0;
COL2 = 0;
COL3 = 0;
COL4 = 0;
ROW1 = 1;
ROW2 = 1;

if(ROW1 == 0||ROW2 == 0)
{
    if(ROW1 == 0&&ROW2 == 0){}
    else if((ROW1 == 1&&ROW2 ==0)||(ROW1 == 0&&ROW2 ==1))
    {
      if(ROW1 == 0){key_board_num = 0;}
      else if(ROW2 ==0){key_board_num = 4;}
   
      COL1 = 1;
      COL2 = 1;
      COL3 = 1;
      COL4 = 1;
      ROW1 = 0;
      ROW2 = 0;
      
      if(COL1 == 0){key_board_num = key_board_num + 1 -1;seg_num++;}
      if(COL2 == 0){key_board_num = key_board_num + 1;seg_num++;}
      if(COL3 == 0){key_board_num = key_board_num + 2;seg_num++;}
      if(COL4 == 0){key_board_num = key_board_num + 3;seg_num++;}
      printf("%d按键按下\r\n",key_board_num);
    }
    COL1 = 0;
    COL2 = 0;
    COL3 = 0;
    COL4 = 0;
    ROW1 = 1;
    ROW2 = 1;
}
else
{
    key_board_num = 0xff;
}
}
void key_Seg(void)
{
seg_num++;
if(seg_num >= 8)    seg_num = 0;//8位结束回0
Display_Seg(~SEG_W[0],SEG_D);
}


程序实现代码
void key_board(void)
{
COL1 = 0;
COL2 = 0;
COL3 = 0;
COL4 = 0;
ROW1 = 1;
ROW2 = 1;

if(ROW1 == 0||ROW2 == 0)
{
    if((ROW1 == 0)&&(ROW2 == 0)){}
    else if(((ROW1 == 1)&&(ROW2 ==0))||((ROW1 == 0)&&(ROW2 ==1)))
    {
      if(ROW1 == 0){key_board_num = 0;}
      else if(ROW2 ==0){key_board_num = 4;}
   
      COL1 = 1;
      COL2 = 1;
      COL3 = 1;
      COL4 = 1;
      ROW1 = 0;
      ROW2 = 0;
      
      if(COL1 == 0){key_board_num = key_board_num + 1 -1;}
      if(COL2 == 0){key_board_num = key_board_num + 1;}
      if(COL3 == 0){key_board_num = key_board_num + 2;}
      if(COL4 == 0){key_board_num = key_board_num + 3;}
      //printf("%d按键按下\r\n",key_board_num);
    }
    COL1 = 0;
    COL2 = 0;
    COL3 = 0;
    COL4 = 0;
    ROW1 = 1;
    ROW2 = 1;
}
else
{
    key_board_num = 0xff;
}
}
void key_Seg(void)
{
Display_Seg(~SEG_W,SEG_D[possward]);
led_num++;
if(led_num >= 8)    led_num = 0;//8位结束回0
}
void write_pow(void)
{
if(key_board_num < 0xff)
{
    key_num ++;
    if(key_num == 5)
    {
      if(seg_num == 0)
      {
      possward[0] = 16;
      possward[1] = 16;
      possward[2] = 16;//o
      possward[3] = 16;//p
      possward[4] = 16;//e
      possward[5] = 16;//n
      possward[6] = 16;
      possward[7] = 16;   
      }
      possward = key_board_num;
      seg_num ++;
      if(seg_num == 8)
      {
      if(possward[0] == 1&&possward[1] == 2&&possward[2] == 3&&possward[3] == 4&&possward[4] == 5&&possward[5] == 6&&possward[6] == 7&&possward[7] == 0)
      {
          possward[0] = 17;
          possward[1] = 1;
          possward[2] = 17;//o
          possward[3] = 1;//p
          possward[4] = 17;//e
          possward[5] = 1;//n
          possward[6] = 17;
          possward[7] = 1;   
      }
      else
      {
          possward[0] = 16;
          possward[1] = 16;
          possward[2] = 16;//o
          possward[3] = 16;//p
          possward[4] = 16;//e
          possward[5] = 16;//n
          possward[6] = 16;
          possward[7] = 16;   
      }
      seg_num = 0;
      }   
    }
}
else
{
    key_num = 0;
}
}


拓展代码包含洗衣机拓展









--哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前

skyalong 发表于 2025-6-13 14:50:26

第十二集 复位系统
摘要1硬件复位2.软件复位
硬件复位            看门狗复位代码,按下按键跳过喂狗超时将复位WDT_CONTR = 0X24;//开启看门狗
    while(1)
    {   
      Task_Pro_Handler_Callback();
      //REC_NUM = UsbOutBuffer-48;//任务3
      if(P33 != 0)
            WDT_CONTR = 0X34;//喂狗
    }
软件复位代码,P32软件复位,P32软件复位并进入下载模式

void key(void)
{
    if(P32 == 0)
    {
      key_num++;
      if(key_num == 5)
      {
            //printf("按键按下\r\n");
            USB_Reset_U();
            IAP_CONTR = 0X20;//软件复位,不进入下载模式
      }   
    }
    else
    {
      key_num = 0;
    }
    if(P33 == 0)
    {
      key_num1++;
      if(key_num1 == 5)
      {
            //printf("按键按下\r\n");
            USB_Reset_U();
            IAP_CONTR = 0X60;//软件复位,进入下载模式
      }   
    }
    else
    {
      key_num1 = 0;
    }
}
课后小练
拓展代码:


            





--哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前


skyalong 发表于 2025-6-18 15:56:41

第十三集 外部中断
摘要1.中断系统介绍2.外部中断介绍3.外部中断用法
中断系统介绍    外部中断      硬件复位任务1:编写外部中断1的程序任务代码:
void Delay3000ms(void)//@24.000MHz
{
    unsigned long edata i;

    _nop_();
    _nop_();
    i = 17999998UL;
    while (i) i--;
}
void INT1_Init(void)
{
    IT1 = 1;            //下降沿中断
    EX1 = 1;            //外部中断1允许
    EA = 1;             //打开总中断
}
void INT_ISR(void) interrupt 2
{
    P21 = !P21;
}
void main(void)
{   
    Sys_init();
    usb_init();                                     //USB CDC 接口配置
    set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
   
    Init_595();
    INT1_Init();
    Timer0_Init();
    EA = 1;
    //Task4();
   
    //WDT_CONTR = 0X24;//开启看门狗


    while(1)
    {   
      //Task_Pro_Handler_Callback();
      //REC_NUM = UsbOutBuffer-48;//任务3
      //if(P33 != 0)
      //WDT_CONTR = 0X35;//喂狗 超时时间1秒
      P20 = !P20;
      Delay3000ms();
    }
}
拓展拓展代码:
void INT1_Init(void)
{
    IT1 = 1;            //下降沿中断
    EX1 = 1;            //外部中断1允许
    EA = 1;             //打开总中断
}
void INT_ISR(void) interrupt 2
{
    P00 = 0;//关灯 光机停止工作 模拟保护
}
void key_start(void)
{
    COL1 = 0;
    COL2 = 0;
    COL3 = 0;
    COL4 = 0;
    ROW1 = 1;
    ROW2 = 1;
   
    if(ROW1 == 0||ROW2 == 0)
    {
      if((ROW1 == 0)&&(ROW2 == 0)){}
      else if(((ROW1 == 1)&&(ROW2 ==0))||((ROW1 == 0)&&(ROW2 ==1)))
      {   
            if(ROW1 == 0){key_board_num = 0;}
            else if(ROW2 ==0){key_board_num = 4;}
      
            COL1 = 1;
            COL2 = 1;
            COL3 = 1;
            COL4 = 1;
            ROW1 = 0;
            ROW2 = 0;
            
            if(COL1 == 0){key_board_num = key_board_num + 1 -1;}
            if(COL2 == 0){key_board_num = key_board_num + 1;}
            if(COL3 == 0){key_board_num = key_board_num + 2;}
            if(COL4 == 0){key_board_num = key_board_num + 3;}
            //printf("%d按键按下\r\n",key_board_num);
      }
      COL1 = 0;
      COL2 = 0;
      COL3 = 0;
      COL4 = 0;
      ROW1 = 1;
      ROW2 = 1;
    }
    else
    {
      key_board_num = 0xff;
    }
}
void main(void)
{   
    Sys_init();
    usb_init();                                     //USB CDC 接口配置
    set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
   
    Init_595();
    INT1_Init();
   
    Timer0_Init();
    EA = 1;
    //Task4();
   
    //WDT_CONTR = 0X24;//开启看门狗

    P0=0x00;
    while(1)
    {   
      //Task_Pro_Handler_Callback();
      //REC_NUM = UsbOutBuffer-48;//任务3
      //if(P33 != 0)
      //WDT_CONTR = 0X35;//喂狗 超时时间1秒
      key_start();
      if(key_board_num == 1)
      {
            P00 = 1;
      }
      //P20 = !P20;
      //Delay3000ms();
    }
}














--哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前


skyalong 发表于 2025-6-24 15:54:53

第十四集 IO中断摘要1.IO中断介绍2.IO中断用法3.中断优先级的设置
IO中断介绍IO中断用法            任务1:编写IO中断的程序
代码:触发中断P20状态取反void P3_IO_Init(void)
{
P3IM0 = 0X00;   //IO中断模式设置为了下降沿
P3IM1 = 0X00;

P3INTE= 0x04;   //打开中断 7654 3210 8421 8421
}
void main(void)
{   
Sys_init();
usb_init();                                     //USB CDC 接口配置
set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
Timer0_Init();
P3_IO_Init();
EA = 1;

P20 = 1;
    while(1)
{
    P21 = !P21;
    Delay3000ms();
}
}
void P3_IO_ISR(void)interrupt 40
{
u8 intf;
intf = P3INTF;
if( intf )      //判断有没有IO触发了中断
{
    P3INTF = 0;
    if( intf & 0x04 )//判断是否是P32按钮按下
    {
      P20 = !P20;
    }
}
}
中断优先级设置

任务2:编写P4端口的IO中断 打断 P3低电平中断的的程序(注意优先级)代码:(将P4改为了P1,P1默认优先级比P3高,P1可以打断P3,P3不能打断P1;修改优先级后给予P3最高优先级后,P3可以打断P1)
void P3_IO_Init(void)
{
P3IM0 = 0X00;   //IO中断模式设置为了下降沿
P3IM1 = 0Xff;

P3INTE= 0x04;   //打开中断 P32 7654 3210 8421 8421

PINIPH|= 0x08;//写入最高优先级
PINIPL|= 0x08;
}
void P1_IO_Init(void)
{
P1IM0 = 0X00;   //IO中断模式设置为了下降沿
P1IM1 = 0Xff;

P1INTE= 0x04;   //打开中断 P12 7654 3210 8421 8421
}
void main(void)
{   
Sys_init();
usb_init();                                     //USB CDC 接口配置
    set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
    Init_595();
Timer0_Init();
P3_IO_Init();
P1_IO_Init();
EA = 1;

P20 = 1;
P22 = 1;
    while(1)
{
    //Task_Pro_Handler_Callback();      //执行功能函数
    Display_Seg(0xfe,0x3f);
}
}
void P3_IO_ISR(void)interrupt 40
{
u8 intf;
intf = P3INTF;
if( intf )      //判断有没有IO触发了中断
{
    P3INTF = 0;
    if( intf & 0x04 )//判断是否是P32按钮按下
    {
      Display_Seg(0xfe,0x5b);
    }
}
}
void P1_IO_ISR(void)interrupt 38
{
u8 intf;
intf = P1INTF;
if( intf )      //判断有没有IO触发了中断
{
    P1INTF = 0;
    if( intf & 0x04 )//判断是否是P32按钮按下
    {
      Display_Seg(0xfe,0x06);
    }
}
}
课后练习

练习代码:void P1_IO_Init(void)
{
P1IM0 = 0X00;   //IO中断模式设置为了下降沿
P1IM1 = 0Xff;

P1INTE= 0x07;   //打开中断 P12 7654 3210 8421 8421
}
void main(void)
{   
Sys_init();
usb_init();                                     //USB CDC 接口配置
    set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数
    Init_595();
Timer0_Init();
//P3_IO_Init();
P1_IO_Init();
EA = 1;

P20 = 1;
P22 = 1;
    while(1)
{
    //Task_Pro_Handler_Callback();      //执行功能函数
    Display_Seg(0xfe,0x3f);
}
}
void P1_IO_ISR(void)interrupt 38
{
u8 intf;
intf = P1INTF;
if( intf )      //判断有没有IO触发了中断
{
    //P1INTF = 0;
    if( intf & 0x04 )//判断是否是P12按钮按下
    {
      Display_Seg(0xfe,0x4f);
      while(1);
    }
    if( intf & 0x02 )//判断是否是P11按钮按下
    {
      Display_Seg(0xfe,0x5b);
      while(1);
    }
    if( intf & 0x01 )//判断是否是P10按钮按下
    {
      Display_Seg(0xfe,0x06);
      while(1);
    }
}
}






--哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前

skyalong 发表于 2025-7-15 16:18:13

第十五集 定时器做计数器摘要1.计数器的作用2.定时器做为计数器的用法3.定时器1测量INT1引脚低电平脉冲宽度
作用用法任务1:编写定时器1计数的的程序(为了方便计数,10个脉冲中断一次)代码main.c#include "config.h"
#include "io.h"
#include "task.h"
#include "tim.h"   
void usb_callback();

void main(void)
{   
    Sys_init();
    usb_init();                                     //USB CDC 接口配置
    set_usb_OUT_callback(usb_callback);             //设置中断回调回调函数

    Timer0_Init();
    TIM1_Count_Init();

    EA = 1;

    while(1)
    {   
      Task_Pro_Handler_Callback();                //执行功能函数
    }
}
void Timer0_Isr(void) interrupt 1
{   
    Task_Marks_Handler_Callback();
}
void usb_callback()
{
    USB_SendData(UsbOutBuffer,OutNumber);         //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
}
time.c#include "tim.h"

u32 Count_T1 = 0;

void TIM1_Count_Init(void)
{
    T1_CT = 1;
    T1_M1 = 0;
    T1_M0 = 0;
    T1_GATE = 0;
   
    TH1 = (65536 - count_num) >> 8;
    TL1 = (65536 - count_num);
   
    P3PU |= 0x20;

    ET1 = 1;
    TR1 = 1;
}
void Timer1_Isr(void) interrupt 3
{
    Count_T1 ++;
}
void T1_Task(void)
{
    u32 count_th_tl = 0;
    count_th_tl = (((u16)TH1 << 8) + ((u16)TL1));
    count_th_tl -= 65526;
    SEG7_ShowLong(Count_T1 * count_num + count_th_tl,10);
}

定时器1测量INT1引脚低电平脉冲宽度任务2:编写INT1测量低电平时间(由按键模拟信号,100us的计数周期计数!)代码:
#include "tim.h"

u32 Count_T1 = 0;

//void TIM1_Count_Init(void)
//{
//T1_CT = 1;
//T1_M1 = 0;
//T1_M0 = 0;
//T1_GATE = 0;
//
//TH1 = (65536 - count_num) >> 8;
//TL1 = (65536 - count_num);
//
//P3PU |= 0x20;

//ET1 = 1;
//TR1 = 1;
//}
//void Timer1_Isr(void) interrupt 3
//{
//Count_T1 ++;
//}
void T1_Task(void)
{
//u32 count_th_tl = 0;
//count_th_tl = (((u16)TH1 << 8) + ((u16)TL1));
//count_th_tl -= 65526;
//SEG7_ShowLong(Count_T1 * count_num + count_th_tl,10);
    SEG7_ShowString("%07.01f",((float)Count_T1)/10);
}
void Timer1_Isr(void) interrupt 3
{
    static u32 count_p33 = 0;
   
    if( P33 == 0 )
    {
      count_p33 ++ ;
    }
    else
    {
      if( count_p33>0 )
      {
            Count_T1 = count_p33;
      }
      count_p33 =0;
    }
}
void Timer1_Init(void)      //100微秒@24.000MHz
{
    AUXR &= 0xBF;         //定时器时钟12T模式
    TMOD &= 0x0F;         //设置定时器模式
    TL1 = 0x38;             //设置定时初始值
    TH1 = 0xFF;             //设置定时初始值
    TF1 = 0;                //清除TF1标志
    TR1 = 1;                //定时器1开始计时
    ET1 = 1;                //使能定时器1中断
}

课后练习练习代码:




--哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前

32位8051-AI 发表于 2025-7-15 16:44:08


推荐优先看的 printf_usb("Hello World !\r\n")及usb不停电下载, 演示视频链接
https://v.stcai.com/sv/1c5eec2-197fcd9b766/1c5eec2-197fcd9b766.mp4
https://v.stcai.com/sv/1fce8086-197cf2b9dd4/1fce8086-197cf2b9dd4.mp4


页: 1 [2]
查看完整版本: 学习《Ai8051U教学视频》心得打卡