找回密码
 立即注册
查看: 185|回复: 17

按键点灯问题

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2025-04-29 15:31:16
已绑定手机

4

主题

37

回帖

154

积分

注册会员

积分
154
发表于 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是可以的

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2025-04-29 15:31:16
已绑定手机

4

主题

37

回帖

154

积分

注册会员

积分
154
发表于 2025-4-8 10:22:35 | 显示全部楼层
请问有大神能帮忙解释一下吗?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2025-4-8 10:36:34 | 显示全部楼层
你从这个程序开始,用最新的USB库,最新的 ISP 软件 V6.95L
截图202504081035022644.jpg

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

截图202504081036261137.jpg

深圳国芯人工智能有限公司-库函数
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2025-04-29 15:31:16
已绑定手机

4

主题

37

回帖

154

积分

注册会员

积分
154
发表于 2025-4-8 10:51:53 | 显示全部楼层
请问在老师的第六章IO演示任务三中,可以按我下面的截图优化吗?我感觉一直对P00取反就行,而且烧录试了下,貌似和老师的实验效果相同
截图202504081050132375.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-8 11:02:39 | 显示全部楼层
cb*** 发表于 2025-4-8 10:22
请问有大神能帮忙解释一下吗?

使用 printf_usb() 替换 printf() 试试,新版库文件USB打印信息默认使用 printf_usb()。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2025-04-29 15:31:16
已绑定手机

4

主题

37

回帖

154

积分

注册会员

积分
154
发表于 2025-4-8 11:08:21 | 显示全部楼层
乘风*** 发表于 2025-4-8 11:02
使用 printf_usb 替换 printf 试试,新版库文件USB打印信息默认使用 printf_usb。
...

是的,看了头文件,里面用的是printf_usb(),确实可以打印,
那我上面的那个截图是否是任务三的替代版本?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2025-4-8 11:17:40 | 显示全部楼层
去抖动,直接延时是可以的,
但我们为深圳大学的 按键去抖动专门写了专业的去抖动程序,

利用主循环反复查询按键状态,利用N次主循环查询,按键还是按下中,来去抖动
===不用 延时/这会堵塞其他任务的执行
===不用 定时器/这会浪费定时器资源


截图202504081115307878.jpg

截图202504081117138885.jpg

截图202504081117353211.jpg



截图202504081121577247.jpg

截图202504081122194642.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2025-4-8 11:24:42 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-04-30 09:58:34
已绑定手机

39

主题

2006

回帖

6841

积分

论坛元老

积分
6841
发表于 2025-4-8 11:26:00 | 显示全部楼层
cb*** 发表于 2025-4-8 10:51
请问在老师的第六章IO演示任务三中,可以按我下面的截图优化吗?我感觉一直对P00取反就行,而且烧录试了下 ...

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

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2025-4-8 11:26:52 | 显示全部楼层
截图202504081126326272.jpg


#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();           //其他事件
        }
}


回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 02:33 , Processed in 0.132379 second(s), 105 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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