王昱顺
发表于 2025-3-3 22:27:09
Ai8051U 使用内部自带的 硬件USB 直接仿真 的演示视频:
https://v.stcai.com/sv/441001ec-1955ec96d2e/441001ec-1955ec96d2e.mp4
视频中使用到的程序:
王昱顺
发表于 2025-3-5 17:34:25
按键控制点灯并使用USB仿真查看汇编代码-演示视频及附带代码
https://v.stcai.com/sv/3ac65752-19565b59541/3ac65752-19565b59541.mp4
代码文件下载:
王昱顺
发表于 2025-3-5 17:38:59
使用USB-CDC读取按键状态并点灯-演示视频
https://v.stcai.com/sv/371ea5b4-19565b5956f/371ea5b4-19565b5956f.mp4
程序文件:
神农鼎
发表于 2025-3-6 19:28:59
本楼附件有参考程序
I/O 口的工作模式 实验建议:
【准双向口/弱上拉】;
【强推挽输出】;
【高阻输入】,内部还有6K上拉电阻配合;
===打开内部上拉6K上拉配合读外部状态
【开漏模式】,内部还有6K上拉电阻配合;
===打开内部上拉6K,就相当于【准双向口/弱上拉】
I/O读外部状态,可以用如下三种模式:
【准双向口/弱上拉】;
【高阻输入】,内部还有6K上拉电阻配合;
===打开内部上拉6K上拉配合读外部状态
【开漏模式】,内部还有6K上拉电阻配合;
===打开内部上拉6K,就相当于【准双向口/弱上拉】
I/O对外输出高/低,可以用如下三种模式:
【准双向口/弱上拉】;
【强推挽输出】;
【开漏模式】
===对外输出低,就是强推挽的低
===对外输出高,就是高阻输入,没电流流进,也没电流流出,灯不亮
P3.2/P3.3/P3.4/P3.5 都有按键接地,建议:
P0口 都有单独的指示灯
实验1, 位操作,用USB直接仿真来调试:
单独 读这几个独立I/O的状态,P3.2/P3.3/P3.4/P3.5
输出到 P0.2/P0.3/P0.4/P0.5 对应的指示灯
单独读时,分别用三种I/O口的工作模式测试下
单独输出时,分别用三种I/O口的工作模式测试下
I/O读外部状态,可以用如下三种模式:
【准双向口/弱上拉】;
【高阻输入】,内部还有6K上拉电阻配合;
===打开内部上拉6K上拉配合读外部状态
【开漏模式】,内部还有6K上拉电阻配合;
===打开内部上拉6K,就相当于【准双向口/弱上拉】
I/O对外输出高/低,可以用如下三种模式:
【准双向口/弱上拉】;
【强推挽输出】;
【开漏模式】
===对外输出低,就是强推挽的低
===对外输出高,就是高阻输入,没电流流进,也没电流流出,灯不亮
实验2, 整组8位端口操作,用USB直接仿真来调试:
整组 读这几个I/O的状态【P3.2/P3.3/P3.4/P3.5】,一次性读全部P3口
整体输出到 【P0.2/P0.3/P0.4/P0.5】在的P0口对应的指示灯
整组读时,分别用三种I/O口的工作模式测试下
整组输出时,分别用三种I/O口的工作模式测试下
I/O读外部状态,可以用如下三种模式:
【准双向口/弱上拉】;
【高阻输入】,内部还有6K上拉电阻配合;
===打开内部上拉6K上拉配合读外部状态
【开漏模式】,内部还有6K上拉电阻配合;
===打开内部上拉6K,就相当于【准双向口/弱上拉】
I/O对外输出高/低,可以用如下三种模式:
【准双向口/弱上拉】;
【强推挽输出】;
【开漏模式】
===对外输出低,就是强推挽的低
===对外输出高,就是高阻输入,没电流流进,也没电流流出,灯不亮
实验三,不用USB仿真,用 USB-CDC通信:
电脑 ISP软件中的,USB-CDC串口助手 通知 单片机读 P3.2/P3.3/P3.4/P3.5的状态。
1,送回 USB-CDC串口助手 显示
2,送到 AIapp-ISP 软件中的 【调试仿真接口 | 擎天柱-LED-PID40】虚拟显示
===通信协议见 【调试仿真接口 | 接口协议及帮助】部分
功能2:控制DIP40的指定组管脚上LED的状态
命令格式:4CH 45H 44H 28H 02H x1 px
命令说明:
第1~4字节:命令头
第5字节:后面有效数据长度
第6字节:P0~P5端口的屏蔽位
(01H:P0, 02H:P1, 04H:P2, 08H:P3, 10H:P4, 20H:P5)
第7字节:端口的状态
使用串口通讯请参考下面的示例发送串口数据
示例1:发送4CH 45H 44H 28H 02H 01H 55H
设置P0口的状态为55H
示例2:发送4CH 45H 44H 28H 02H 04H AAH
设置P2口的状态为AAH
库函数声明:void LED40_SetPort(BYTE port, BYTE dat);
*** 包含库函数的头文件后,不用另外声明 ***
项目中包含库函数后,可直接调用下面的库函数
库函数调用:LED40_SetPort(0, 0x55); //设置P0口输出55H
LED40_SetPort(1, 0xaa); //设置P1口输出AAH
功能3:控制DIP40的指定管脚输出高电平
命令格式:4CH 45H 44H 28H 02H 00H px ...
命令说明:
第1~4字节:命令头
第5字节:后面有效数据长度
第6字节:固定为00H
第7字节:端口的状态数据px
px的bit7:固定为1
px的bit6~bit3:指定第几组管脚(0:P0,1:P1,2:P2,...)
px的bit2~bit0:指定管脚的第几位(0:bit0,1:bit1,...)
使用串口通讯请参考下面的示例发送串口数据
示例1:发送4CH 45H 44H 28H 02H 00H 83H
设置P0.3口输出高电平
示例2:发送4CH 45H 44H 28H 02H 00H a5H
设置P4.5口输出高电平
库函数声明:void LED40_SetBit(BYTE port, BYTE bt);
*** 包含库函数的头文件后,不用另外声明 ***
项目中包含库函数后,可直接调用下面的库函数
库函数调用:LED40_SetBit(0, 3); //设置P0.3口输出高电平
LED40_SetBit(4, 5); //设置P4.5口输出高电平
功能4:控制DIP40的指定管脚输出低电平
命令格式:4CH 45H 44H 28H 02H 00H px ...
命令说明:
第1~4字节:命令头
第5字节:后面有效数据长度
第6字节:固定为00H
第7字节:端口的状态数据px
px的bit7:固定为0
px的bit6~bit3:指定第几组管脚(0:P0,1:P1,2:P2,...)
px的bit2~bit0:指定管脚的第几位(0:bit0,1:bit1,...)
使用串口通讯请参考下面的示例发送串口数据
示例1:发送4CH 45H 44H 28H 02H 00H 03H
设置P0.3口输出低电平
示例2:发送4CH 45H 44H 28H 02H 00H 25H
设置P4.5口输出低电平
库函数声明:void LED40_ClrBit(BYTE port, BYTE bt);
*** 包含库函数的头文件后,不用另外声明 ***
项目中包含库函数后,可直接调用下面的库函数
库函数调用:LED40_ClrBit(0, 3); //设置P0.3口输出低电平
LED40_ClrBit(4, 5); //设置P4.5口输出低电平
神农鼎
发表于 2025-3-10 13:14:37
I/O 口章节的实验5的思考:
实验5,I/O口 行列式按键扫描 大型实战,利用主循环次数去抖动
如1个按键要判断为正常按下,而不是抖动,
假定需要该按键保持按下持续保持为低状态时间是 50mS ~ 200mS;
假定1个主循环的运行时间大概 10mS ~ 30mS
则如发现某个按键按下,需要连续 6次主循环都能读到该按键按下
===如发现多个按键按下,则归0,重新开始
调整按键的灵敏度只需要修改,
===【判断按键已按下的时间,即读到为低经历了多少次主循环的次数】
Project9 实验程序 简要说明,详见附件:
1,上电P0口的8个LED闪烁3次当作开机画面,
2,接下来行列按键矩阵扫描,
A, 每扫描到一个键,蜂鸣器发不同的声音,
8个按键对应Do/Re/Mi/Fa/So/La/Si/Do,
B, 同时在电脑端的CDC串口助手中显示“KeyX被按下”
王昱顺
发表于 2025-3-10 14:24:43
矩阵按键部分的拓展视频讲解,原理讲解,程序逐行解释:
I/O 口章节的实验5的思考:
实验5,I/O口 行列式按键扫描 大型实战,利用主循环次数去抖动
神农鼎
发表于 2025-3-15 08:43:37
传统外部中断 INT0/INT1/INT2/INT3/INT4 实验的思考
INT0/P3.2 外部中断实验演示程序:
1,边缘触发中断
P3.2设置为高阻输入,打开内部上拉电阻;
或
P3.2设置为准双向口,打开内部上拉电阻;
INT2/P3.2设置为 边缘触发中断;
将 P3.2按键按下,不松开;
进中断后,读到是 低,下降沿,点亮 P0.0,退出中断服务程序;
松开 P3.2中断;
进中断后,读到是 高,上升沿,点亮 P0.7, 退出中断服务程序;
利用仿真,可以设置运行到断点处,捕捉当前程序运行到哪,
是 下降沿,还是上升沿
2,下降沿触发中断
王昱顺
发表于 2025-3-17 11:45:39
USB仿真:
INT0 / INT1 模式0:边沿触发中断 /【下降沿,上升沿】;
INT0 / INT1 模式1:下降沿中断;并点灯指示状态,仿真断点功能讲解
USB仿真:用户程序主动控制 I/O口拉低 INT2/INT3 触发 下降沿中断
王昱顺
发表于 2025-3-23 14:54:53
深圳大学,实验课演示视频
定时器部分讲解-T0/T1 定时中断,并点灯,及更简单的USB-CDC回传信息
Timer0 定时 2S 产生中断,Timer1 定时 500mS 产生中断;
思考题:T2 定时 20mS,T3 定时 1mS ,T4 定时 200uS 产生中断
深圳大学,实验课演示视频
RTC实时时钟部分讲解-闹钟定时,及更简单的USB-CDC与电脑通信
神农鼎
发表于 2025-3-23 16:19:15
Timer0 定时 2S 产生中断
Timer1 定时 500mS 秒产生中断
思考题:
Timer2 定时 20mS 产生中断
Timer3 定时 1mS 秒产生中断
Timer4 定时 200uS 秒产生中断
#include <AI8051U.H>
#include "ai_usb.h"
bit t0_flag = 0, t1_flag = 0;
void Timer0_Isr(void) interrupt 1
{
P00 = ~P00;
t0_flag = 1;
}
void Timer0_Init(void) //2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void Timer1_Isr(void) interrupt 3
{
P07 = ~P07;
t1_flag = 1;
}
void Timer1_Init(void) //500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
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 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
usb_init();
EA = 1;
Timer0_Init();
Timer1_Init();
P40 = 0;
while(1)
{
if(t0_flag)
{
t0_flag = 0;
printf_usb("Timer0 Int\r\n");
}
if(t1_flag)
{
t1_flag = 0;
printf_usb("Timer1 Int\r\n");
}
}
}