srkxrolz
发表于 2025-6-21 14:49:22
<p>实验1USB_Print函数的基本使用过程</p>
<ol>
<li>创建项目</li>
</ol>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps1.jpg" alt="" /><br />
<img src="data/attachment/forum/202506/21/144533pf55dtdvtk5tt5e5.png" alt="图片1.png" title="图片1.png" /></p>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps2.jpg" alt="" /><br />
<img src="data/attachment/forum/202506/21/144551a1l155y5l9eoyr9y.png" alt="图片1.png" title="图片1.png" /></p>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps3.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202506/21/144626skv57v6zi0oiay57.png" alt="图片1.png" title="图片1.png" /><br />
<img src="data/attachment/forum/202506/21/144609bc5ddhiuh6c6uh6l.png" alt="图片1.png" title="图片1.png" /></p>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps4.jpg" alt="" /></p>
<ol start="2">
<li>获得最新的头文件和usb库文件</li>
</ol>
<p>头文件从stc-isp中获取</p>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps5.jpg" alt="" /><br />
<img src="data/attachment/forum/202506/21/144724yakc5ve0h6ul0zu1.png" alt="图片1.png" title="图片1.png" /></p>
<p>网站上空用获取USb库文件和其他参考的函数文件</p>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps6.jpg" alt="" /><br />
<img src="data/attachment/forum/202506/21/144735g9zakve9zg5145mm.png" alt="图片2.png" title="图片2.png" /></p>
<p>本实验基础程序框架包含4个file</p>
<p>Ai8051u.h</p>
<p>Ai_usb.h</p>
<p>stc_usb_cdc_32g.LIB//这里采用CDC查询方式的库</p>
<p>Main.c //我们的程序主体</p>
<ol start="3">
<li>程序工程中添加这几个文件</li>
</ol>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps7.jpg" alt="" /><br />
<img src="data/attachment/forum/202506/21/144758hg8goynbao1pqwy2.png" alt="图片3.png" title="图片3.png" /></p>
<ol start="4">
<li>编写main文件</li>
</ol>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps8.jpg" alt="" /><br />
<img src="data/attachment/forum/202506/21/144809t7bhgbeeacvhcbav.png" alt="图片4.png" title="图片4.png" /></p>
<ol start="5">
<li>
<p>编译下载 ,观察串口助手输出</p>
<p><img src="data/attachment/forum/202506/21/144819xcs8ycgd68fsf9sk.png" alt="图片5.png" title="图片5.png" /></p>
</li>
</ol>
<p><img src="file:///C:\Users\Administrator\AppData\Local\Temp\ksohtml14596\wps9.jpg" alt="" /><a href="forum.php?mod=attachment&aid=105353" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:实验1.rar</a></p>
srkxrolz
发表于 2025-6-21 14:56:28
实验2 查询方式实现usb输入
#include "ai8051u.h"#include "ai_usb.h"void main(){ EAXFR=1; //允许访问扩展特殊寄存器 WTST=0;// CKCON=0; // usb_init(); EA=1;//中断总开关 while(1){ //printf_usb("Hello World \r\n"); if (bUsbOutReady){ if(UsbOutBuffer==6)printf_usb("Hello World \r\n"); if(UsbOutBuffer==7)printf_usb("拆哪? \r\n"); usb_OUT_done(); }
srkxrolz
发表于 2025-6-21 15:05:12
实验3 使用中断的方式进行usbprinf
srkxrolz
发表于 2025-6-22 00:54:51
第九课:数码管与HC595芯片的使用数码管的结构:共阴共阳接法 3461AS7.3中 AS=单色BS=双色 试验箱上使用了两个74HC595芯片级联,形成一个用两字节的数据控制这8位数码管的效果,高8位用于控制段选(数码管显示的字符),低八位控制位选(选择哪一个位置进行显示). 74hc595时序信号:SCK 时钟线 上升沿移位寄存器会把SER上的电平读入, RCK出现上升沿的时候会把移位寄存器上的数据通过Q0-Q7进行输出.移位寄存器在收到超过8位数据的时候会按顺序吧数据通过Q7’传送给下一个芯片,试验箱上的引脚定义SCk=P32RCK=P35SER=P34两个595共用SCK和RCk第一个的Q7’输出给第二个的SER u8 SMG_POSITION[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; u8 SMG_NUM[] = { 0x3F, /*'0', 0*/ 0x06, /*'1', 1*/ 0x5B, /*'2', 2*/ 0x4F, /*'3', 3*/ 0x66, /*'4', 4*/ 0x6D, /*'5', 5*/ 0x7D, /*'6', 6*/ 0x07, /*'7', 7*/ 0x7F, /*'8', 8*/ 0x6F, /*'9', 9*/ 0x77, /*'A', 10*/ 0x7C, /*'B', 11*/ 0x39, /*'C', 12*/ 0x5E, /*'D', 13*/ 0x79, /*'E', 14*/ 0x71, /*'F', 15*/ 0x40, /*'-', 16*/ 0x00, /*' ', 17*/ 0x80, /*'.', 18*/};void hc595_send(u8 dat){ u8 i; for (i = 0; i < 8; i++) { dat <<= 1; HC595_DIO = CY; HC595_SCK = 1; HC595_SCK = 0; }} void smg_disp(u8 cha, u8 index){ hc595_send(SMG_NUM); // 发送段选 hc595_send(SMG_POSITION); // 发送位选 HC595_RCK = 1; HC595_RCK = 0; if (++index >= 7) index = 0;}void led_40(){ u8 cod; cod = 0x0f; // p0-p3 这八位从高到低代表 p7-p0 cod = P0; // P0^1 高电平 cod = P1; // P1^1 高电平 cod = P2; // P2^1 高电平 cod = P3; // P3^1 高电平 LED40_SendData(cod, 5);} void SMG_PC(){ SEG7_ShowString("1234567abc");} void smg_display(){ u8 displayer_buff[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}, i; for (i = 0; i < sizeof(displayer_buff) / sizeof(displayer_buff); i++) { smg_disp(SMG_NUM], SMG_POSITION); } // printf("smg_disp! \r\n"); smg_disp(0, 0); SMG_PC(); led_40();}
srkxrolz
发表于 2025-6-22 09:58:12
第十课:介绍STC-isp中的虚拟调试接口
Stc-isp 提供了一个模拟上位机工具,用于帮助没有试验箱硬件的伙伴调试程序.
DIP40_LED为例介绍了虚拟接口的原理
功能4: 控制DIP40的各个管脚上LED的状态
以此为例,stc-isp的串口助手在收到一串数据后会重绘界面模拟单片机IO口电平效果,
具体单片机通过串口发送给上位机的数据格式为带命令头的数据串,其中数据格式定义为
固定4字节命令”4CH 45H 44H 28H”然后跟一个字节表示后面的具体端口数据长度,后面数据第一个字节通过8位指定要控制p7-p0 ,接着就是具体要设置的端口的具体值,每一个字节代表一组端口从p0-p7,不需要控制的端口不用写在里面,
Usb库中提供了简便函数空用省去命令头的编写,只需要使用数组定义好需要用户设置的部分即可LED40_SendData(cod, 5);
void led_40()
{
u8 cod;
cod = 0x0f; // p0-p3 这八位从高到低代表 p7-p0
cod = P0; // P0^1 高电平
cod = P1; // P1^1 高电平
cod = P2; // P2^1 高电平
cod = P3; // P3^1 高电平
LED40_SendData(cod, 5);
}
其他还提供几个函数,但功能类似
void LED40_SendData(BYTE *dat, BYTE size); //发送多个端口组
void LED40_SetPort(BYTE port, BYTE dat); //设置指定端口组为某组状态
void LED40_SetBit(BYTE port, BYTE bt); //设置指定端口组某一位为1
void LED40_ClrBit(BYTE port, BYTE bt); //设置指定端口组某一位为0
// p2流水灯 P10 闪烁
void lsd()
{
static u8 p2_flag = 0xfe, p10_flag = 0;
p2_flag <<= 1;
p2_flag = p2_flag + 1;
// P2 = p2_flag;
LED40_SetPort(2,p2_flag);
if (p2_flag == 0xff)
p2_flag = 0xfe;
if (p10_flag == 0)
{
p10_flag = 1;
LED40_SetBit(1, 0);
}
else
{
p10_flag = 0;
LED40_ClrBit(1, 0);
}
}
虚拟数码管
int SEG7_ShowString(const char *fmt, ...);
void SEG7_ShowLong(long n, char radix);
void SEG7_ShowFloat(float f);
void SEG7_ShowCode(BYTE *cod);
上位机的虚拟键盘
If(bUsbOutReady){
Num=UsbOutBuffer-48;//ascii字符转数字
}
srkxrolz
发表于 2025-6-22 11:16:46
第十二集 复位系统
单片机提供了五种复位方式
1, 上电复位
2, 低压复位
3, 复位引脚低脉冲复位
4, 看门狗复位
5, 软件复位给IAP_CONTR的SWRST置1
Stc中对上电复位时间有影响的地方
Stc-isp选项中上电复位使用较长延时
//此选项默认选中,会影响大概100ms
下次冷启动 p32 p33为0才可下载程序
//这里悬空的时候默认为0会进入isp下载程序,所以不下载程序空用用5.1K电阻拉高跳过isp, 影响几十毫秒
允许低压复位(禁止低压中断)
//默认选中 也就是VCC低于阈值直接系统复位,不勾选会产生一个软件中断,中断程序中空用点亮一个低压报警led作为提示, 低压状态下不要执行保存数据的操作,容易乱码
复位脚做IO口
//默认勾选的 p47为IO口 ,需要勾选后空用接一个300r电阻和按钮到地, 按下就可以复位
看们狗复位
//有一个独立累加计数器,加到溢出就复位,需要定时清空这个计时器防止复位,
void wdt_init()
{
WDT_CONTR = 0x00; // 设置看门狗定时器时钟分配系数为最低2分频,并重置其他控制位
IDL_WDT=1; // 设置看门狗定时器在空闲模式下继续计数
CLR_WDT=1; // 清除看门狗定时器计数值
EN_WDT =1; // 使能看门狗
}
void wdt_feed()
{
CLR_WDT = 1; // 清除看门狗计数值
}
软件复位
void soft_reset()
{
IAP_CONTR = 0x20; // 正常复位到main函数
IAP_CONTR = 0x60; // 复位到isp下载模式
}
srkxrolz
发表于 2025-6-22 12:07:45
第十三集外部中断
1.中断系统
8051u中提供了73个中断源,使用大于31的中断时需要在使用中断号扩展补丁
例INT0:P32按下后捕获到边沿跳变后置位IE0经过EX0中断允许和总开关到用户中断函数
IT0=0, 上下边沿均可触发IT0=1下降沿触发
IE0 INt0的中断标志位 ,响应中断函数后硬件自动清零
EX0 允许int0中断
EA=1 打开总开关
//p32 int0中断初始化
void int0_init(){
IT0 = 1; // 设置INT0为下降沿触发
EX0 = 1; // 使能INT0中断
EA = 1;// 全局中断使能
}
void int0_isr(void) interrupt 0
{
// 在这里处理INT0中断
// 例如,切换LED状态或执行其他操作
P10 = ~P10; // 切换P10的状态
}
2.外部中断
由外部信号触发的中断
3.内部中断
内部因素导致得到中断
神农鼎
发表于 2025-6-22 15:07:39
一起学AiCube@Ai8051U 定时器0/1,INT0/INT1,中断组合应用实验打卡 - 学习打卡区 | 感悟 国芯技术交流网站 - AI32位8051交流社区
神农鼎
发表于 2025-6-22 15:13:10
//外部中断INT0和INT1控制点灯并USB仿真
#include <AI8051U.H> //包含AI8051U的头文件
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
bit int0_flag = 0; //定义1个位变量,INT0事件位变量标志,记录INT0已产生中断
// 供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务,不堵塞其他中断
bit int1_flag = 0; //定义1个位变量,INT1事件位变量标志,记录INT1已产生中断
// 供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务,不堵塞其他中断
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
// P3M0 = 0x00; P3M1 = 0x00; //P32、P33设置为准双向口
P3M0 = 0x00; P3M1 = 0xff; //P32、P33设置为高阻输入(需要同步开启上拉电阻)
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
P3PU = 0x0c; //P32、P33打开上拉电阻
IT0 = 0; //使能 INT0 上升沿和下降沿中断
// IT0 = 1; //使能 INT0 下降沿中断
EX0 = 1; //使能 INT0 中断
// IT1 = 0; //使能 INT1 上升沿和下降沿中断
IT1 = 1; //使能 INT1 下降沿中断
EX1 = 1; //使能 INT1 中断
IE0 = 0; //清INT0中断标志
IE1 = 0; //清INT1中断标志
EA = 1; //打开所有中断
P40 = 0; //打开LED灯供电
int0_flag = 0; //初始化用户标志位
int1_flag = 0; //初始化用户标志位
while(1)
{
if(int0_flag) //主循环中查询,INT0是否已产生中断,是否有需要处理的INT 0事件
{
int0_flag = 0; //清0,INT0事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(int1_flag) //主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
int1_flag = 0; //清0,INT1事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
}
}
void int0_isr(void) interrupt INT0_VECTOR
{
int0_flag = 1; // int0_flag置1是通知主循环处理部分INT0中断事件不需要特急处理的任务
//置1,记录INT0已产生中断,供主循环查询判断有无需处理的INT0任务
if(INT0) //边沿中断,进入后再次判断电平从而判断是什么样的电平
{
P00 = 0; //判断为高电平,则当前为上升沿,点亮P00端口上的LED灯
_nop_(); //可以在这里插入断点进行观察现象
P00 = 1; //关闭LED灯
}
else
{
P07 = 0; //判断为低电平,则当前为下降沿,点亮P07端口上的LED灯
_nop_(); //可以在这里插入断点进行观察现象
P07 = 1; //关闭LED灯
}
}
void int1_isr(void) interrupt INT1_VECTOR
{
int1_flag = 1; // int1_flag置1是通知主循环处理部分INT1中断事件不需要特急处理的任务
//置1,记录INT1已产生中断,供主循环查询判断有无需处理的INT1任务
P04 = 0; //点亮P04端口上的LED灯
_nop_(); //可以在这里插入断点观察现象
P04 = 1; //关闭LED灯
}
srkxrolz
发表于 7 天前
第十四集 io中断89c51的io中断只有2个,现在8051u的所有io端口都可以配置中断并由4级优先级都支持唤醒Io中断模式有四种下降沿m1=0m0=0上升沿m1=0m0=1 低电平m1=1m0=0 高电平m1=1m0=1 每组IO电口有两个配置寄存器P0IM0 和P0IM1 可以控制每组中的8个IO口. 通过M1与M0确定触发方式 中断使能寄存器 P0INTE中段每一位控制对应IO口的中断enable中断标志位 P0INTF 每一位表示中断使得否触发, 有中断触发就置1 软件手动清0void P33_int_init(){ P3IM0 &= ~0x08; // 设置P33为下降沿触发 P3IM1 &= ~0x08; // 设置P33为下降沿触发 P3INTE |= 0x08; // 使能P33中断 EA = 1; // 全局中断使能}void P33_int_isr(void) interrupt 40 // P3整个组的中断服务程序{ if (P3INTF & 0x08) // 检测P33中断标志位 { P3INTF &= ~0x08; // 清除P33中断标志位 // 在这里处理P33中断 // 例如,切换LED状态或执行其他操作 P11 = ~P11; // 切换P11的状态 }} 优先级寄存器PINIPLPINIPH优先级0最低优先级 PINIPH=0 PINIPL=0优先级1低优先级 PINIPH=0 PINIPL=1优先级2高优先级 PINIPH=1 PINIPL=0优先级3最高优先级 PINIPH=1 PINIPL=1