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

【已送实验箱】LED点灯学习

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-8 09:16:36 | 显示全部楼层
第十三集    简易多任务处理



应用模块化的编程(.c+.h)
1、创建程序文件三步
   1.1新建文件并保存
   1.2添加工程
   1.3添加引用路径

2、引用定义都在.h文件
         sbit 名称=P10;
         #define  名称 P10
3、函数定义三步
     定义
     声明
     调用

修饰符extern用在变量或者函数的声明前,用来说明”此变量/函数是在别处定义的,要在此处引用“ 。
举例1:如果文件a.c需要引用b.c中变量int V,就可以在a.c中申明extern int V,然后就可以引用变量V.
举例2:如果文件a.c需要引用b.c中变量int V,就可以在b.h中申明extern int V,然后a.c调用b.h就可以引用变量V.  
注意extern修饰的变量不能赋初值

4、bdata位寻址变量的使用
            
                     a.c                                                  a.h
u8  bdata  LED  =0X00;                       exten  u8 bdata LED;
sbit  LED0 = LED^0;                           exten  bit   LED0;
sbit  LED1 = LED^1;                           exten  bit   LED1;

5、用模块化编程方式将LED&数码管、按健、蜂鸣器、定时器集成在一个工程中,完成多个功能。
6、模块化编程中讲了for循环应用
       u8  i=0;
       u8  t=0;
     for (i=0;i<8;i++)    //i<8,i后自加1次,条件为真,执行for循环内部语句,i=8,i不小于,条件不为成立,跳出循环语句。
     {   
           t++;  
      }
7、讲了static用法
void  SEG_fre(void )
{
   static  u8  num = 0 ;//变量前有static修饰时, num赋初值只1次,下次就为1,再下次为2 。
   if(num<7)
   {
       ;
    }
   num++;
}

8、讲了按键状态机应用
20.png




回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-9 11:14:47 | 显示全部楼层

第十四讲   矩阵按键
1、讲了按键原理图
截图202401091006205063.jpg

按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。
第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。

第三步:  行列组合一下就可判断出是哪一个按键按下了。

2、矩阵按键部分程序
/************延时函数*****************/
void MateixKEY_delay(void)
{
    u8 i =60;
   while(--i);
}
/*****矩阵按键读取当前是哪一个按钮按下*********/
u8  MateixKEY_Read(void)
{
     u8 keystate;                              //表示当前的按键的状态值
    //第一步:现将P0.0-P0.3输出低电平◇P0.6-P0.7输出高电平◇如果有按键按下◇
    MateixKEY  = 0xC0;                    //1100 0000
    MateixKEY_delay();

    keystate = ( MateixKEY ^ 0xC0);  // 0100 0000 ^1100 0000 =1000 000
  
   //第二步◇现将P0.0-P0.3输出高电平◇P0.6-P0.7输出低电平◇如果有按键按下,按下的那一行IO就会变成低电平。
   MateixKEY= OXOf;                     //0000 1111
   MateixKEY_delay();
   keystate |=(MateixKEY ^OX0f);     //0000  1110 ^ 00001111 = 0000 0001 | 1000 0000 =0x81。
  //第三步:行列组合一下就可以判断出是哪个按键按下了。
   printf("0x%02x\r\n",keystate);
   return keystate:


}


void  main()

      u8 KEY_NUM = 0; //
      sys_init () ;
      usb_init () ;
      Timer0_Init ();
      EA = 1;
      LED = 0XFF;
      while(1)
      {
         if(DeviceState !=DEVSTATE_CONFIGURED)
          continue;
         if( bUsbOutReady )
         {
          usb_OUT_done();
           }
         if(TIM_10MS_Flag==1 )
         {
            TIM_10MS_Flag=0;
            KEY_NUM=  MateixKEY_Read();
           SEG7 = void  main()

      u8 KEY_NUM = 0; //
      sys_init () ;
      usb_init () ;
      Timer0_Init ();
      EA = 1;
      LED = 0XFF;
      while(1)
      {
         if(DeviceState !=DEVSTATE_CONFIGURED)
          continue;
         if( bUsbOutReady )
         {
          usb_OUT_done();
           }
         if(TIM_10MS_Flag==1 )
         {
            TIM_10MS_Flag=0;
            KEY_NUM =  MateixKEY_Read();
            SEG7 = KEY_NUM;
         }

  }




3、密码锁编程

截图202401081945547949.jpg
密码锁需求:1.通过LEDO模拟门锁状态,LED点亮表示门锁打开,熄灭表示门锁锁上2.增加8位数码管,可以动态
显示8位的密码,无密码时显示“......"3.通过矩阵按键可以输入1-8的数字表示密码,并依次显示在数码管上;4.每
输入一个数字,蜂鸣器响20ms表示有数字按下5.密码正确打开LED0,密码错误蜂鸣响2秒。#include "COMM/stc.h"
#ifndef _ _ KEY_
#define_ _ KEY_


#include"COM/stc.h"

#include"COM/usb.h"


#define  KEY   P3   //P32-P35
#define  KEY1  2  //按键1

#define  KEY1  3  //按键2

#define  KEY1  4  //按键3

#define  KEY1  5  //按键4

#define  MateixKEY   P0  //定义矩阵按键引脚



#define KEY NOPRESS      0    //按键未按下
#define KEY_FILCKER      1    //按键消抖

#define KEY PRESS          2   //单击
#define KEY PRESSOVER  3   //单击结束
#define KEY LONGPRESS   4  //长按3秒

#define KEY LONGOVER    5  //长按结束
#define KEY_RELAX           6  //按键松开

密码锁部分程序如下

/*****矩阵按键读取当前是哪一个按钮按下*********/
u8  MateixKEY_Read(void)
{
     u8 keystate;                              //表示当前的按键的状态值
     u8 key_val = 0;                          //表示当前按键的键码
    //第一步:现将P0.0-P0.3输出低电平◇P0.6-P0.7输出高电平◇如果有按键按下◇
    MateixKEY  = 0xC0;                    //1100 0000
    MateixKEY_delay();

    keystate = ( MateixKEY ^ 0xC0);  // 0100 0000 ^1100 0000 =1000 000
  
   //第二步◇现将P0.0-P0.3输出高电平◇P0.6-P0.7输出低电平◇如果有按键按下,按下的那一行IO就会变成低电平。
   MateixKEY= OXOf;                     //0000 1111
   MateixKEY_delay();
   keystate |=(MateixKEY ^OX0f);     //0000  1110 ^ 00001111 = 0000 0001 | 1000 0000 =0x81。
  //第三步:行列组合一下就可以判断出是哪个按键按下了。
   printf("0x%02x\r\n",keystate);
   switch(keystate)
   {  
        case 0x41  : key_val =1;
                break;
        case 0x42  : key_val =2;
                break;
        case 0x44  : key_val =3;
                break;
        case 0x48  : key_val =4;
                break;
        case 0x81  : key_val =5;
                 break;
        case 0x82  : key_val =6;
                 break;   
        case 0x84  : key_val =7;
                 break;
        case 0x88  : key_val =8;
                 break;
         default :   key_val =0;
                  break;
     }
return keystate;
}

void  main()

      u8 KEY_NUM = 0; // 保存矩阵按键的键码
      u8 KEY_Str  =0;  //表示当前输入几个密码位
      sys_init () ;
      usb_init () ;
      Timer0_Init ();
      EA = 1;
      LED = 0XFF;
      while(1)
      {
         if(DeviceState !=DEVSTATE_CONFIGURED)
          continue;
         if( bUsbOutReady )
         {
          usb_OUT_done();
           }
         if(TIM_10MS_Flag==1 )
         {
            TIM_10MS_Flag=0;
            KEY_NUM =  MateixKEY_Read( );
             if(KEY_NUM>0 )
            {
              BEEP_ON(2);   //蜂鸣器2ms
               Show_tab[KEY_str] = KEY_NUM;
              KEY_Str++;
                if(KEY_Str[0] ==1)&&(KEY_Str[1] ==2)&&(KEY_Str[2] ==3)&&(KEY_Str[3] ==4)&&(KEY_Str[4] ==5)&&(KEY_Str[5] ==6)&&(KEY_Str[6] ==7)
                {
                        LED0 = 0; //灯亮
                }   
                else
                {
                  BEEN_ON(200) ;//密码错误,蜂鸣器响2秒
                 }
                  SEG0=SEG1=SEG2=SEG3=SEG4=SEG5=SEG=6SEG7=21
                  }
            }
            KEY_NUM = 0;
      }








回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-9 12:51:42 | 显示全部楼层
第15集 外部中断

1、中断系统

中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
当中央处理机 CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,
再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中2、什么是外部中断

外部中断就是在单片机的一个引脚上,由于外部因素导致了一个电平的变化(比如由高变低),而通过捕获这个变化,单片机内部自主运行的
程序就会被暂时打断,转而去执行相应的中断处理程序,执行完后又回到原来中断的地方继续执行原来的程序。


3、外部中断使用方法
截图202401091239338080.jpg
   截图202401091240208295.jpg
   截图202401091240537941.jpg
   截图202401091241184723.jpg


4、外部部分程序

void  INT0_Init(void)
{
    IT0 = 1;//下降沿中断
    EX0 = 1;//允许中断
    IE0 = 0;//清除中断标志位
}


void  main()

      u8 KEY_NUM = 0;
      sys_init () ;
      usb_init () ;
      Timer0_Init ();
       INT0_Init( );
       EA = 1;
      LED = 0XFF;
      while(1)
      {
         if(DeviceState !=DEVSTATE_CONFIGURED)
          continue;
         if( bUsbOutReady )
         {
          usb_OUT_done();
           }
          for(i=0;i<8;i++)
          {
            LED =(1<<i);
             delay_ms(500);
          }
          if( P33 == 0  )
          SEG1 +=1;
     }

}
     
void   INT0_ Isr (void)  interrupt  0
{
          SEG0  +=1;   
}   
   






回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-10 08:14:29 | 显示全部楼层
第16集 IO中断

1、外部中断与IO中断区别
    外部中断适用用单此信号,检测信号上升沿或下降沿。  
    IO口中断适用于持续进入中断信号,检测信号为高电平或低电平,如按键一直按下信号。

2、什么是IO口中断
截图202401100812088062.jpg
截图202401100813113162.jpg

截图202401100814029036.jpg


3、实例-简易中央门禁控制系统
1).用8个按键代表每个门的门锁开关,8个LED作为每个门的工作状态,点亮表示门已经打开,熄灭表示门打开。
2).如遇突发火灾,按下应急按钮立刻打开所有门锁,方便人逃生。
3).按下应急按钮后,所有按钮门锁不能上锁
4).松开应急按钮后,倒计时5秒后恢复之前的状态,并可以操作门锁,

简易中央门禁控制系统部分程序

u16  Tme_countDown =0;
void  Time0_init (void)   //1毫秒,24MHZ, 12分频
{
   AUXR &=  0X7F;
   TMOD &= 0XF0;

    TL0 = 0X30;
    TH0 = 0XF8;
    TF0 =0;
     TR0 = 1;
     ET0 = 1;
     IP = 0X02; //设置为最高优先集
     IPH =0X02;
}


void  P3Exit_Init(void)
{
    P3IM0 = 0X00;
    P3IM1 = 0XFF;   //低电平中断
   P3INTE = 0X20;  //P35中断  0010  0000
}

void  main()

      u8  LOCK_State =0xff;//门锁工作状态
      u8 KEY_NUM = 0; // 保存矩阵按键的键码
      u8 KEY_Str  =0;  //表示当前输入几个密码位
      sys_init () ;
      usb_init () ;
      Timer0_Init ();
       P3Exit_Init();
      EA = 1;
      LED =LOCK_State ;
      while(1)
      {
         if(DeviceState !=DEVSTATE_CONFIGURED)
          continue;
         if( bUsbOutReady )
         {
          usb_OUT_done();
           }
         if(TIM_10MS_Flag==1 )
         {
            TIM_10MS_Flag=0;
            if( Tme_countDown ==0)
            {
                KEY_NUM =  MateixKEY_Read( );
                 BEEP_RUN();
                 if(KEY_NUM>0 )
                 {

                   BEEP_ON(2);   //蜂鸣器2ms

                    LOCK_State  ^= (1<<   KEY_NUM-1)  //获取当前第几个按键按下,(1-8)-1

                   }

                   LED =   LOCK_State;

                   SEG0 = 20;// 熄灭数码管

                }

               else

               {

                 Tme_countDown--;

                 SEG0 = Tme_countDown/100+1;   // 500/100   499


                 }   

              }
           }      
      }         
              
void  P3Exit)_Isr(void)    interrupt   40
{
    u8 intf ;
     intf = P3INIF ;//读取中断标志位
   if( intf)
   {
      P3INIF =0;
      if(intf &0x20) //P35按键按下   0010 0000
      {
          LED =0X00;  //打开所有门锁
          SEG0 = 5 ;  //数码管持续显示5
           Tme_countDown = 500;
       }
   }

}

截图202401100813364319.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-10 10:45:11 | 显示全部楼层
第二集  开发板有哪些功能

1、开发板功能有:LED点灯、数码管显示、电压比较、红外发射、红外接收、蜂鸣器、调试接口、RS232电路、FLASH扩展、232接口、USB接口、LED、LCD接口、独立按键、矩阵按键、24C02、DAC、PWM模拟、基准电压、ADC、18B20、
NTC测温。
2、讲了STC32G12K128单片机资源。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-10 10:55:11 | 显示全部楼层
第三集  开发环境搭建和程序下载

1、讲了KEIL安装和使用
2、讲了STC_ISP程序下载
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-10 10:55:12 | 显示全部楼层
第三集  开发环境搭建和程序下载

1、讲了KEIL安装和使用
2、讲了STC_ISP程序下载
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:259
  • 最近打卡:2025-04-02 20:10:12

21

主题

80

回帖

1343

积分

金牌会员

积分
1343
发表于 2024-1-11 11:07:13 | 显示全部楼层
本帖最后由 17141200320 于 2024-1-11 15:15 编辑

第十七集  模数转化器ADC


1.模数转换器是什么:
     模数转换器即A/D转换器,或简称ADC (Analog-to-、digital converter),通常是指一个将模拟信号转变为数字信号的电子元件。
模拟信号 ->电压.
数字信号 -> 0和1组成的二进制数

利用图形和表格方式描述了AD转化过程
截图202401111102583119.jpg

截图202401111103261874.jpg





截图202401111104031031.jpg





截图202401111105153584.jpg
截图202401111106139198.jpg
截图202401111107042192.jpg







2、ADC查询方式部分程序
#define  ADC_CHECK  0  //查询
#define  ADC_Isr     1     //中断
#define  ADC_FUNC     ADC_Isr   // 最终选择

# if   ADC_FUNC  ==  ADC_CHECK
void  ADC_Init(void)   //查询ADCC初始化
{
    P1M0 = 0x00;
    P1M1 =0X01;   //设置P10为高阻输入
    ADCTIM = 0X3F;
    ADCCFG =0X2F;   //数据右对齐,时钟选择sysclk/2/16最慢
   ADC_POWER = 1;
}



u16 ADC_Read(u8 no)
{
  u16 adcval;
   ADC_CONTER &= 0Xf0;   //清空通道
   ADC_CONTTER  |= no;   //选择通道
   ADC_Start = 1;               //开启ADC转化
    _nop_();                       //空操作指令

    _nop_();
  while(!ADC_FLAG);          //等待ADC转换结束
  ADC_FLAG = 0;
  adcval = (ADC_RES<<8)+ADC_RESL;   
  return   adcval;
}


u16 ADC_CAL_Voltage(u16 num)   //转换电压
{
   return  num*2.5*1000/4096;
}

void  main()

      u8 KEY_NUM = 0; //
      sys_init () ;
      usb_init () ;
      Timer0_Init ();
       ADC_Init();
      EA = 1;
      LED = 0XFF;
      while(1)
      {
         if(DeviceState !=DEVSTATE_CONFIGURED)
          continue;
         if( bUsbOutReady )
         {
          usb_OUT_done();
           }
         if(TIM_10MS_Flag==1 )
         {
            TIM_10MS_Flag=0;
             ADC_VAL = ADC_Read();
             Printf ("当前ADC数\xfd值:%d\r\n ",(int)ADC_VAL ,   (int)ADC_CAL_Voltage(ADC_VAL));    //ad值和相对的电压
         }

  }


#else if   ADC_FUNC  ==  ADC_Isr


void  ADC_Init(void)   //ADC中断初始化
{
    P1M0 = 0x00;
    P1M1 =0X01;   //设置P10为高阻输入
    ADCTIM = 0X3F;
    ADCCFG =0X2F;   //数据右对齐,时钟选择sysclk/2/16最慢
   ADC_POWER = 1;
    EADC = 1;
}

void  ADC_Isr(void)  interrupt  5
{
      ADC_FLAG = 0;
      ADC_VAL=   (ADC_RES<<8)+ADC_RESL;  
      ADC_Start = 1;
}

#else
#endif










回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-6-19 20:11 , Processed in 0.144314 second(s), 82 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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