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&amp;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
页: 1 [2] 3
查看完整版本: 记录我的8051u学习过程