cbai 发表于 2025-4-8 10:16:54

按键点灯问题

#include "ai8051u.h"
#include "intrins.h"
#include "stc32_stc8_usb.h"
/*
任务1:按下P32按钮灯亮,松开P32按钮灯灭;
任务2:按下P32按钮灯灭,松开P32按钮灯亮;
任务3:按一下灯亮,按一下灯灭
*/


void main(void) {
      WTST = 0;                                                                                  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1;                                                                                 //扩展寄存器(XFR)访问使能
    CKCON = 0;                                                                                 //提高访问XRAM速度
      // 按照原理图,点亮8个LED灯需要按下P40总开关和给8个LED灯低电平
      // 1、相应的GPIO口初始化
      P0M1 = 0; P0M0 = 0;
      P1M1 = 0; P1M0 = 0;
      P2M1 = 0; P2M0 = 0;
      P3M1 = 0; P3M0 = 0;
      P4M1 = 0; P4M0 = 0;
      P5M1 = 0; P5M0 = 0;
      P6M1 = 0; P6M0 = 0;
      P7M1 = 0; P7M0 = 0;
      usb_init();
      IE |= 0x80; // 允许USB中断
      EA = 1; // 开启中断总开关
      
      P40 = 0;
      
      
      // 2、P40低电平
      // 3、P00 P01 P02 P03 P04 P05 P06 P07低电平
      

      while(1) {
                if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
//            printf_usb("1. Read Num:%d\n", OutNumber);
//            printf_usb("2. Read Num:%d\n", OutNumber);
//            printf_usb("3. Read Num:%d\n", OutNumber);
//            printf_usb("4. Read Num:%d\n", OutNumber);

            usb_OUT_done();
      }
                // 任务1:按下P32按钮灯亮,松开P32按钮灯灭;
                // 判断P32按键是否按下
                if(P32 == 0) {
                        P00 = 0;
//                        printf("按钮按下\r\n");
                }
                else{
                        P00 = 1;
//                        printf("按钮松开\r\n");
                }
      }
}


我的代码是上面,但是打开那两句printf烧录后按键没反应,需要注释掉才能按键有反应,请问是怎么回事?我看到老师的视频中第三个任务有printf是可以的

cbai 发表于 2025-4-8 10:22:35

请问有大神能帮忙解释一下吗?

神农鼎 发表于 2025-4-8 10:36:34

你从这个程序开始,用最新的USB库,最新的 ISP 软件 V6.95L


https://www.stcaimcu.com/forum.p ... id=16731&pid=157245



深圳国芯人工智能有限公司-库函数

cbai 发表于 2025-4-8 10:51:53

请问在老师的第六章IO演示任务三中,可以按我下面的截图优化吗?我感觉一直对P00取反就行,而且烧录试了下,貌似和老师的实验效果相同

乘风飞扬 发表于 2025-4-8 11:02:39

cbai 发表于 2025-4-8 10:22
请问有大神能帮忙解释一下吗?
使用 printf_usb() 替换 printf() 试试,新版库文件USB打印信息默认使用 printf_usb()。

cbai 发表于 2025-4-8 11:08:21

乘风飞扬 发表于 2025-4-8 11:02
使用 printf_usb 替换 printf 试试,新版库文件USB打印信息默认使用 printf_usb。
...
是的,看了头文件,里面用的是printf_usb(),确实可以打印,
那我上面的那个截图是否是任务三的替代版本?

神农鼎 发表于 2025-4-8 11:17:40

去抖动,直接延时是可以的,
但我们为深圳大学的 按键去抖动专门写了专业的去抖动程序,
利用主循环反复查询按键状态,利用N次主循环查询,按键还是按下中,来去抖动
===不用 延时/这会堵塞其他任务的执行
===不用 定时器/这会浪费定时器资源













神农鼎 发表于 2025-4-8 11:24:42



https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=15176&pid=150915

程序下载链接如上

乘风飞扬 发表于 2025-4-8 11:26:00

cbai 发表于 2025-4-8 10:51
请问在老师的第六章IO演示任务三中,可以按我下面的截图优化吗?我感觉一直对P00取反就行,而且烧录试了下 ...

这段代码理论上是可以实现按一次按键亮灯,再按一次按键灭灯的效果。

神农鼎 发表于 2025-4-8 11:26:52




#include <AI8051U.H>                                     //包含AI8051U的头文件
#include "ai_usb.h"                                       //使用usb所需要包含的头文件
#include "intrins.h"


bit keyok;                      //按键按下标志
unsigned char keycode;          //定义变量,保存按键键码
unsigned char debounce;         //按键去抖动

void Delay1ms(void)                     //@40.000MHz,延时1ms
{
      unsigned long edata i;

      _nop_();
      _nop_();
      _nop_();
      i = 9998UL;
      while (i) i--;
}

void DelayXms(int n)            //延时函数,延时x(ms)
      {
    while (n--)
      Delay1ms();
}

void DelayXus(int n)                        //@40.000MHz,延时x(us)
{
      unsigned long edata i;

    while (n--)
    {
            i = 8UL;
            while (i) i--;
    }
}

void BootLogo(void)             //开机画面
{
    P0 = 0x00;                  //8个LED全部点亮
    DelayXms(200);            //延时200ms
    P0 = 0xff;                  //8个LED全部熄灭
    DelayXms(200);            //延时200ms
    P0 = 0x00;                  //8个LED全部点亮
    DelayXms(200);            //延时200ms
    P0 = 0xff;                  //8个LED全部熄灭
    DelayXms(200);            //延时200ms
    P0 = 0x00;                  //8个LED全部点亮
    DelayXms(200);            //延时200ms
    P0 = 0xff;                  //8个LED全部熄灭
    DelayXms(200);            //延时200ms
}

void DetectTemp(void)         //检测当前温度
{
}

void ControlTemp(void)          //控制当前温度
{
}

void OtherEvent(void)         //其他事件
{
    DelayXms(10);               //假定其他事件处理时间为10ms
}

void Beep(int tone)             //蜂鸣器程序
{                               //实验箱上的是无源蜂鸣器,需要持续输出高低电平蜂鸣器才会发声
    int i;
   
    for (i = 0; i < 50; i++)
    {
      P50 = 1;                //打开蜂鸣器控制三极管
      DelayXus(tone);         //延时(修改延时时间可改变蜂鸣器的音调)
      P50 = 0;                //关闭蜂鸣器控制三极管
      DelayXus(tone);         //延时
    }
}

void KeyEvents(void)            //执行有效按键对应的任务
{
    if (keyok)                  //判断按键按下标志
    {
      keyok = 0;            //清除标志
      
      switch (keycode)      //处理不同的按键键码
      {
      case 0: Beep(956); break;//Key0事件,使用蜂鸣器发Do
      case 1: Beep(851); break;//Key1事件,使用蜂鸣器发Re
      case 2: Beep(758); break;//Key2事件,使用蜂鸣器发Mi
      case 3: Beep(716); break;//Key3事件,使用蜂鸣器发Fa
      case 4: Beep(638); break;//Key4事件,使用蜂鸣器发So
      case 5: Beep(568); break;//Key5事件,使用蜂鸣器发La
      case 6: Beep(506); break;//Key6事件,使用蜂鸣器发Si
      case 7: Beep(478); break;//Key7事件,使用蜂鸣器发Do
      }
    }
}

void ScanKey(void)            //检测按键状态
{
    unsigned char key;          //按键扫描键码
   
    key = 0xff;               //初始化扫描变量
    P0 = 0xff;                  //P0输出输出高使能内部若上拉,准备读取按键状态
    P06 = 0; P07 = 1;         //准备扫描第1行
      NOP12();                                        //等待12个nop再读取按键状态,NOP12()这个宏已在AI8051U.H的头文件中定义
    if (!P00) key = 0;          //检查第1行第1列按键是否被按下
    else if (!P01) key = 1;   //检查第1行第2列按键是否被按下
    else if (!P02) key = 2;   //检查第1行第3列按键是否被按下
    else if (!P03) key = 3;   //检查第1行第4列按键是否被按下
    else                        //如果第一行没有按键按下则扫描下一行
    {
      P07 = 0;                //准备扫描第2行
      P06 = 1;
                NOP12();                              //等待12个nop再读取按键状态,NOP12()这个宏已在AI8051U.H的头文件中定义
      if (!P00) key = 4;      //检查第2行第1列按键是否被按下
      else if (!P01) key = 5; //检查第2行第2列按键是否被按下
      else if (!P02) key = 6; //检查第2行第3列按键是否被按下
      else if (!P03) key = 7; //检查第2行第4列按键是否被按下
    }
    P0 = 0xff;                  //恢复P0口状态
   
    if (key != keycode)         //判断按键状态是否有变化
    {
      keycode = key;          //保存键码
      debounce = 5;         //初始化去抖动变量
    }
    else
    {
      if (debounce != 0)      //是否
      {
            if (--debounce == 0)//判断去抖动是否已经完成
            {
                if (keycode != 0xff) //判断是松开按键还是按下按键,键码为0表示是松开按键,非0为按下按键
                {
                  keyok = 1;//设置按键按下标志
                  printf_usb("Key%d被按下\r\n", keycode);
                }
            }
      }
    }
}

void main(void)
{
      EAXFR = 1;                                       //允许访问扩展的特殊寄存器,XFR
      WTST = 0;                                       //设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
      CKCON = 0;                                       //设置访问片内的xdata速度,赋值为 0 表示用最快速度访问,不增加额外的等待时间
      P0M0 = 0x00; P0M1 = 0x00;      //设置 P0 口为准双向口模式
      P1M0 = 0x00; P1M1 = 0x00;         //设置 P1 口为准双向口模式
      P2M0 = 0x00; P2M1 = 0x00;         //设置 P2 口为准双向口模式
      P3M0 = 0x00; P3M1 = 0x00;         //设置 P3 口为准双向口模式
      P4M0 = 0x00; P4M1 = 0x00;         //设置 P4 口为准双向口模式
      P5M0 = 0x01; P5M1 = 0x00;         //设置 P5.0 口为强推挽, 其他设置为准双向口模式
      P6M0 = 0x00; P6M1 = 0x00;         //设置 P6 口为准双向口模式
      P7M0 = 0x00; P7M1 = 0x00;         //设置 P7 口为准双向口模式
    keycode = 0xff;             //初始化键码(0~7为有效键码,0xff为无效键码)
    keyok = 0;                  //初始化按键标志

      usb_init();                                 //USB 接口配置
      EA = 1;                                                //打开总中断

      while (DeviceState != DEVSTATE_CONFIGURED);         //等待USB完成配置

    P50 = 0;                  //关闭蜂鸣器
      P40 = 0;                                        //打开LED部分的供电
    BootLogo();               //显示开机画面, 8个LED同时闪烁3次

      while(1)
      {                           //假定整个主循环的执行时间为10ms左右
      ScanKey();            //按键扫描
      KeyEvents();            //按键事件处理
      
      DetectTemp();         //温度检查任务
      ControlTemp();          //温度控制任务
      OtherEvent();         //其他事件
      }
}


页: [1] 2
查看完整版本: 按键点灯问题