按键点灯问题
#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是可以的
请问有大神能帮忙解释一下吗? 你从这个程序开始,用最新的USB库,最新的 ISP 软件 V6.95L
https://www.stcaimcu.com/forum.p ... id=16731&pid=157245
深圳国芯人工智能有限公司-库函数
请问在老师的第六章IO演示任务三中,可以按我下面的截图优化吗?我感觉一直对P00取反就行,而且烧录试了下,貌似和老师的实验效果相同 cbai 发表于 2025-4-8 10:22
请问有大神能帮忙解释一下吗?
使用 printf_usb() 替换 printf() 试试,新版库文件USB打印信息默认使用 printf_usb()。
乘风飞扬 发表于 2025-4-8 11:02
使用 printf_usb 替换 printf 试试,新版库文件USB打印信息默认使用 printf_usb。
...
是的,看了头文件,里面用的是printf_usb(),确实可以打印,
那我上面的那个截图是否是任务三的替代版本?
去抖动,直接延时是可以的,
但我们为深圳大学的 按键去抖动专门写了专业的去抖动程序,
利用主循环反复查询按键状态,利用N次主循环查询,按键还是按下中,来去抖动
===不用 延时/这会堵塞其他任务的执行
===不用 定时器/这会浪费定时器资源
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=15176&pid=150915
程序下载链接如上
cbai 发表于 2025-4-8 10:51
请问在老师的第六章IO演示任务三中,可以按我下面的截图优化吗?我感觉一直对P00取反就行,而且烧录试了下 ...
这段代码理论上是可以实现按一次按键亮灯,再按一次按键灭灯的效果。
#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