17141200320 发表于 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
u8bdataLED=0X00;                     extenu8 bdata LED;
sbitLED0 = LED^0;                           extenbit   LED0;
sbitLED1 = LED^1;                           extenbit   LED1;

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

8、讲了按键状态机应用





17141200320 发表于 2024-1-9 11:14:47


第十四讲   矩阵按键
1、讲了按键原理图


按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。
第一步:现将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);
}
/*****矩阵按键读取当前是哪一个按钮按下*********/
u8MateixKEY_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);   //00001110 ^ 00001111 = 0000 0001 | 1000 0000 =0x81。
//第三步:行列组合一下就可以判断出是哪个按键按下了。
   printf("0x%02x\r\n",keystate);
   return keystate:


}


voidmain()

      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 = voidmain()

      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、密码锁编程


密码锁需求: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"


#defineKEY   P3   //P32-P35
#defineKEY12//按键1

#defineKEY13//按键2

#defineKEY14//按键3

#defineKEY15//按键4

#defineMateixKEY   P0//定义矩阵按键引脚



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

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

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

密码锁部分程序如下

/*****矩阵按键读取当前是哪一个按钮按下*********/
u8MateixKEY_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);   //00001110 ^ 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;
}

voidmain()

      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_NUM;
            KEY_Str++;
                if(KEY_Str ==1)&&(KEY_Str ==2)&&(KEY_Str ==3)&&(KEY_Str ==4)&&(KEY_Str ==5)&&(KEY_Str ==6)&&(KEY_Str ==7)
                {
                        LED0 = 0; //灯亮
                }   
                else
                {
                  BEEN_ON(200) ;//密码错误,蜂鸣器响2秒
               }
                  SEG0=SEG1=SEG2=SEG3=SEG4=SEG5=SEG=6SEG7=21
                  }
            }
            KEY_NUM = 0;
      }








17141200320 发表于 2024-1-9 12:51:42

第15集 外部中断

1、中断系统

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

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


3、外部中断使用方法






4、外部部分程序


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


voidmain()

      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)interrupt0
{
          SEG0+=1;   
}   
   







17141200320 发表于 2024-1-10 08:14:29

第16集 IO中断

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

2、什么是IO口中断






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

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

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

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


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

voidmain()

      u8LOCK_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

               }   
            }
         }      
      }         
            
voidP3Exit)_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;
       }
   }

}

17141200320 发表于 2024-1-10 10:45:11

第二集开发板有哪些功能

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

17141200320 发表于 2024-1-10 10:55:11

第三集开发环境搭建和程序下载

1、讲了KEIL安装和使用
2、讲了STC_ISP程序下载

17141200320 发表于 2024-1-10 10:55:12

第三集开发环境搭建和程序下载

1、讲了KEIL安装和使用
2、讲了STC_ISP程序下载

17141200320 发表于 2024-1-11 11:07:13

本帖最后由 17141200320 于 2024-1-11 15:15 编辑

第十七集模数转化器ADC


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

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
























2、ADC查询方式部分程序
#defineADC_CHECK0//查询
#defineADC_Isr   1   //中断
#defineADC_FUNC   ADC_Isr   // 最终选择

# if   ADC_FUNC==ADC_CHECK
voidADC_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)   //转换电压
{
   returnnum*2.5*1000/4096;
}

voidmain()

      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


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

voidADC_Isr(void)interrupt5
{
      ADC_FLAG = 0;
      ADC_VAL=   (ADC_RES<<8)+ADC_RESL;
      ADC_Start = 1;
}

#else
#endif











页: 1 2 [3]
查看完整版本: 【已送实验箱】LED点灯学习