mikeybie 发表于 2024-12-16 10:00:40

AI8051U学习打卡(一)

<h1>AI8051U学习打卡(一)</h1>
<h1>1. <strong>AI8051U硬件资源</strong></h1>
<p><strong>Ai8051U-LQFP48 比普通 M0/M3,比 32F103C8T6 强太多的地方:</strong></p>
<ol>
<li>**Ai8051U有TFPU@120MHz, 算力比他强, uS级硬件三角函数/浮点运算器; **</li>
<li><strong>Ai8051U的抗干扰比他强;</strong></li>
<li><strong>Ai8051U的内部复位是专业级的复位电路,彻底省外部复位;</strong></li>
<li>**Ai8051U的内部时钟完全满足串口通信要求,4组串口; **</li>
<li>**Ai8051U-LQFP48有 QSPI, i8080/M6800-TFT 接口,32F103C8T6没有; **</li>
<li><strong>Ai8051U的PWM支持硬件移相@120MHz ;</strong></li>
<li><strong>Ai8051U是 34K SRAM ;</strong></li>
<li><strong>Ai8051U是 自带硬件USB, 1个芯片就能直接USB连接电脑仿真/下载,</strong></li>
<li><strong>全球唯一 ===这个开发生态,全球最强 Ai8051U-LQFP48, RMB2.3含税</strong></li>
</ol>
<p><img src="data/attachment/forum/202412/16/100001xzczqna8a80gdzaq.jpg" alt="" /></p>
<h1>2. <strong>开发环境搭建</strong></h1>
<p><strong>官网下载地址:</strong><a href="https://www.stcai.com/cp_ai8051uxl">深圳国芯人工智能有限公司-产品_AI8051U系列</a></p>
<p><strong>必备资料清单:</strong></p>
<p><img src="data/attachment/forum/202412/16/100000hihflk4xlxodxiai.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100000z0ueu9qj0oje6zac.jpg" alt="" /></p>
<h2>2.1. <strong>keil-C251软件设置</strong></h2>
<p><img src="data/attachment/forum/202412/16/100000kj6jqlm6kast96ej.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100000ddbibdv11b5vdrlz.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100001h7nw2brf1gz152g1.jpg" alt="" /></p>

mikeybie 发表于 2024-12-16 10:03:13

<h1>AI8051U学习打卡(二)</h1>
<h2><strong>2.1点灯实验</strong></h2>
<p><img src="data/attachment/forum/202412/16/100155lr7xx8100v4lx697.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100155lhj0d4zhjjrjsk44.jpg" alt="" /></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

typedef         unsigned char        u8;
typedef         unsigned int        u16;
typedef         unsigned long        u32;

#define MAIN_Fosc      24000000UL

//==========================================================================


/*************本地常量声明    **************/


/*************IO口定义    **************/

/*************本地变量声明    **************/


/*************本地函数声明    **************/

voiddelay_ms(u8 ms);

/****************外部函数声明和外部变量声明 *****************/


/******************** 主函数 **************************/
void main(void)
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P40 = 0;                //LED Power On

    while(1)
    {
      P00 = 0;                //LED On
      delay_ms(250);
      P00 = 1;                //LED Off

      P01 = 0;                //LED On
      delay_ms(250);
      P01 = 1;                //LED Off

      P02 = 0;                //LED On
      delay_ms(250);
      P02 = 1;                //LED Off

      P03 = 0;                //LED On
      delay_ms(250);
      P03 = 1;                //LED Off

      P04 = 0;                //LED On
      delay_ms(250);
      P04 = 1;                //LED Off

      P05 = 0;                //LED On
      delay_ms(250);
      P05 = 1;                //LED Off

      P06 = 0;                //LED On
      delay_ms(250);
      P06 = 1;                //LED Off

      P07 = 0;                //LED On
      delay_ms(250);
      P07 = 1;                //LED Off
    }
}

//========================================================================
// 函数: voiddelay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
voiddelay_ms(u8 ms)
{
   u16 i;
   do{
          i = MAIN_Fosc / 6000;
          while(--i);
   }while(--ms);
}
</code></pre>
<h2>2.2. <strong>STC-link下载</strong></h2>
<p><strong>打开一个点灯程序,按如下配置成功烧录,成功点亮led。</strong></p>
<p><strong>下面那个复位引脚作io也不要勾选,不然复位按键失效。</strong></p>
<p><img src="data/attachment/forum/202412/16/100155t6rv1jzhiw818htz.jpg" alt="" /></p>
<h2>实物演示:</h2>
<p><img src="data/attachment/forum/202412/16/101232odz1bz2bfc2sbgc1.gif" alt="e94c643a0dc57bd1f0f6de2820d8de22.gif" title="e94c643a0dc57bd1f0f6de2820d8de22.gif" /></p>

mikeybie 发表于 2024-12-16 10:05:22

<h1>AI8051U学习打卡(三)</h1>
<h1>3. <strong>USB不停电下载(usb-cdc-uart)</strong></h1>
<p><img src="data/attachment/forum/202412/16/100350sn1lmjt661l15o6v.jpg" alt="" /></p>
<p><strong>没下载不停电下载程序之前,还是之前的流水灯代码,这个时候直接只用一根usb线连接电脑是没有任何反应的。</strong></p>
<p><strong>图方便就用那个STC-link来下载。插上STC-link之后就显示出来串口了,如图所示。</strong></p>
<p><img src="data/attachment/forum/202412/16/100350ib8exltqhadyduhi.jpg" alt="" /></p>
<p><strong>然后和上一节一样正常直接烧录下面的代码就行。</strong></p>
<p><img src="data/attachment/forum/202412/16/100350zmdnrfdqmogjgxrw.jpg" alt="" /></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================

/******************** 主函数 **************************/
void main(void)
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                                     //USB CDC 接口配置

    IE2 |= 0X80;                            //开启USB中断
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
    }
}
</code></pre>
<p><strong>不用STC-link,再次只用一个usb线连接电脑,发现识别到一个新的串口,这个是usb虚拟串口,支持任意波特率。</strong></p>
<p><img src="data/attachment/forum/202412/16/100350errgbjl2qbmj2nlx.jpg" alt="" /></p>
<p><strong>之后就可以直接用这个不断电下载程序了,也不用STC-link了,但是代码框架不能改,如果重新烧录之前流水灯的代码,就会又识别不到了,又只能用STC-link或者断电下载了。</strong></p>
<p><img src="data/attachment/forum/202412/16/101420qrz055khsw0i52wd.png" alt="image.png" title="image.png" /></p>
<h2>3.1. <strong>printf打印</strong></h2>
<p><img src="data/attachment/forum/202412/16/100615t3wfd2o8666aa8sn.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100615eog1wj3orl34y8r2.jpg" alt="" /><img src="data/attachment/forum/202412/16/100615tg7ez92jexi96o9j.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100615jnuf1u963mm0jiz7.jpg" alt="" /></p>

mikeybie 发表于 2024-12-16 10:10:25

<h1>AI8051U学习打卡(四)</h1>
<h1>4. <strong>GPIO输入输出</strong></h1>
<p><img src="data/attachment/forum/202412/16/100952zulguuc7cxdvgzg4.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/100952ehtt6nvrwpdt55dr.jpg" alt="" /></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

uint8_t led_state = 0;
/******************** 主函数 **************************/
void main(void)
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                                     //USB CDC 接口配置

    IE2 |= 0X80;                            //开启USB中断
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
   
      if(P32 == 0)//判断按键按下
      {
            Delay20ms();//按键消抖
            if(P32 == 0)
            {
               led_state ^=1;
               P00 = led_state;
               printf(&quot;led_state:%d\r\n&quot;,led_state);
            
               while(P32 == 0); //等待按键松开
            }
      }
    }
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/113404u1vpz5vp9v3pq1i1.jpg" alt="" /><img src="data/attachment/forum/202412/16/113404a99zvbvz6nsxs0zp.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/113404zuroq4gg8un8q4ff.jpg" alt="" /></p>

mikeybie 发表于 2024-12-16 11:24:08

<h1>AI8051U学习打卡(五)</h1>
<h1>5. <strong>定时器中断</strong></h1>
<h2>5.1. <strong>定时器资源</strong></h2>
<p><img src="data/attachment/forum/202412/16/112219eeacihq9s4777p37.jpg" alt="" /></p>
<h2>5.2. <strong>软件配置定时器</strong></h2>
<p><img src="data/attachment/forum/202412/16/112220irjfot0tzf0rwy43.jpg" alt="" /></p>
<p><strong>下载代码之后led成功每隔3秒亮灭一次,然后串口也能打印按下次数。</strong></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

void Timer0_Init(void)                //3秒@40MHz
{
        TM0PS = 0x98;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
        TMOD &amp;= 0xF0;                        //设置定时器模式
        TL0 = 0xB1;                                //设置定时初始值
        TH0 = 0x00;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

uint8_t led_state = 0;
/******************** 主函数 **************************/
void main(void)
{
    uint8_t cnt = 0;
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
      
      if(P32 == 0)//判断按键按下
      {
            Delay20ms();//按键消抖
            if(P32 == 0)
            {
               cnt++;
                printf(&quot;按键按下次数\xfd:%d\r\n&quot;,cnt);
               while(P32 == 0); //等待按键松开
            }
      }
    }
}

void Timer0_Isr(void) interrupt 1
{
   led_state ^=1;
   P00 = led_state;
}
</code></pre>
<h2>5.3. <strong>bug解决</strong></h2>
<h3>5.3.1. <strong>keil警告</strong></h3>
<p><img src="data/attachment/forum/202412/16/112220hfyv98gga38gg8uu.jpg" alt="" /></p>
<h3>5.3.2. <strong>串口打印乱码</strong></h3>
<p><img src="data/attachment/forum/202412/16/112219m3eme65zcysg1156.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/112220w35xel2ql77z2vl0.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/112220d79i76n6ff9zl9y6.jpg" alt="" /></p>
<p><img src="data/attachment/forum/202412/16/112220p8ch97s9r77v7bgc.jpg" alt="" /></p>
<h2>5.4. <strong>定时器时间计算</strong></h2>
<p><img src="data/attachment/forum/202412/16/112221g5uzb8u0cuu0afjz.jpg" alt="" /></p>
<p><strong>TM0PS:分频系数(psc)</strong></p>
<p><strong>(65536-):目标计数值(arr)</strong></p>
<p><strong>Sysclk:系统时钟(40Mhz)</strong></p>
<p><strong>eg:</strong></p>
<p><img src="data/attachment/forum/202412/16/112220skct4xplukt2zrr8.jpg" alt="" /></p>
<p><strong>TM0PS = 152</strong></p>
<p><strong> = 177</strong></p>
<p><strong>(152+1)*(65536 - 177)*12/40000000 = 2.9999781s</strong></p>
<h3>5.4.1. <strong>定时器0延时3s关灯</strong></h3>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

void Timer0_Init(void)                //3秒@40MHz
{
        TM0PS = 0x98;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
        TMOD &amp;= 0xF0;                        //设置定时器模式
        TL0 = 0xB1;                                //设置定时初始值
        TH0 = 0x00;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

uint8_t led_state = 0;
/******************** 主函数 **************************/
void main(void)
{
//    uint8_t cnt = 0;
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
//    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
      
      //任务1
//      if(P32 == 0)//判断按键按下
//      {
//            Delay20ms();//按键消抖
//            if(P32 == 0)
//            {
//               cnt++;
//                printf(&quot;按键按下次数\xfd:%d\r\n&quot;,cnt);
//               while(P32 == 0); //等待按键松开
//            }
//      }
      //任务2
      if(P32 == 0)//判断按键按下
      {
            Delay20ms();//按键消抖
            if(P32 == 0)
            {
               P00 = 0;//开灯
               Timer0_Init();                  //定时器0初始化
               printf(&quot;定时器开启,灯亮\r\n&quot;);
               while(P32 == 0); //等待按键松开
            }
      }
    }
}

void Timer0_Isr(void) interrupt 1
{
//   led_state ^=1;
//   P00 = led_state;
   P00 = 1;//关灯
   TR0 = 0;//关闭定时器
   printf(&quot;定时器关闭,灯灭\r\n&quot;);
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/112220yjyjj1s15j591vej.jpg" alt="" /><img src="https://www.stcaimcu.com/data/attachment/forum/202412/16/112313xjsmmxf7d9ns6993.gif" alt="8b4b4b6f89bb99854d2d3afd28eec964.gif" title="8b4b4b6f89bb99854d2d3afd28eec964.gif" /></p>
<h3>5.4.2. <strong>灯交替闪烁</strong></h3>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

//void Timer0_Init(void)                //3秒@40MHz
//{
//        TM0PS = 0x98;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
//        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
//        TMOD &amp;= 0xF0;                        //设置定时器模式
//        TL0 = 0xB1;                                //设置定时初始值
//        TH0 = 0x00;                                //设置定时初始值
//        TF0 = 0;                                //清除TF0标志
//        TR0 = 1;                                //定时器0开始计时
//        ET0 = 1;                                //使能定时器0中断
//}

void Timer0_Init(void)                //500毫秒@40MHz
{
        TM0PS = 0x19;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
        TMOD &amp;= 0xF0;                        //设置定时器模式
        TL0 = 0x99;                                //设置定时初始值
        TH0 = 0x05;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

uint8_t led_state = 0;
uint8_t run_state = 0;
/******************** 主函数 **************************/
void main(void)
{
//    uint8_t cnt = 0;
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
//    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
      
      //任务1
//      if(P32 == 0)//判断按键按下
//      {
//            Delay20ms();//按键消抖
//            if(P32 == 0)
//            {
//               cnt++;
//                printf(&quot;按键按下次数\xfd:%d\r\n&quot;,cnt);
//               while(P32 == 0); //等待按键松开
//            }
//      }
      //任务2
//      if(P32 == 0)//判断按键按下
//      {
//            Delay20ms();//按键消抖
//            if(P32 == 0)
//            {
//               P00 = 0;//开灯
//               Timer0_Init();                  //定时器0初始化
//               printf(&quot;定时器开启,灯亮\r\n&quot;);
//               while(P32 == 0); //等待按键松开
//            }
//      }
      //任务3
      if(P32 == 0)//判断按键按下
      {
            Delay20ms();//按键消抖
            if(P32 == 0)
            {
               run_state ^= 1;
               if(run_state == 1)
               {
                   Timer0_Init();                  //定时器0初始化
                   printf(&quot;定时器开启,灯开始闪\r\n&quot;);
               }
               else
               {
                  P00 = 1;//关灯
                  P01 = 1;//关灯
                   TR0 = 0;
                   printf(&quot;定时器关闭,灯停止闪\r\n&quot;);
               }
               while(P32 == 0); //等待按键松开
            }
      }
    }
}

void Timer0_Isr(void) interrupt 1
{
//   led_state ^=1;
//   P00 = led_state;
//   P00 = 1;//关灯
//   TR0 = 0;//关闭定时器
//   printf(&quot;定时器关闭,灯灭\r\n&quot;);
   led_state ^=1;
   P00 = led_state;
   P01 = !led_state;
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/112221pxjjij672v7jo9a3.jpg" alt="" /><img src="data/attachment/forum/202412/16/112221v6ohgp6v60zdgxdv.jpg" alt="" /></p>

272761180 发表于 2024-12-16 12:29:36

<p>贴主的笔记很详细,给你点个赞<img alt="qiang" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/qiang.gif" title="qiang" /></p>
<p>希望你能继续坚持下去</p>

mikeybie 发表于 2024-12-16 16:03:24

<h1>AI8051U学习打卡(六)</h1>
<h1>6. <strong>定时器任务调度</strong></h1>
<h2>6.1. <strong>任务1:</strong></h2>
<p><strong>用一个定时器实现这个任务。LED1实现0.3秒取反一次,LED2实现0.6</strong></p>
<p><strong>秒取反一次,LED3实现0.9秒取反一次。</strong></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

uint16_t Timer0_cnt ={0,0,0};//定时器0任务周期时间数组
uint8_t i;

void Timer0_Init(void)                //1毫秒@40MHz
{
        TM0PS = 0x00;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
        TMOD &amp;= 0xF0;                        //设置定时器模式
        TL0 = 0xFB;                                //设置定时初始值
        TH0 = 0xF2;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

uint8_t led1_state = 0;
uint8_t led2_state = 0;
uint8_t led3_state = 0;

uint8_t run_state = 0;
/******************** 主函数 **************************/
void main(void)
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
      
      //任务1
      if(Timer0_cnt &gt;= 300)
      {
            Timer0_cnt = 0;
            led1_state ^= 1;
            P00 = led1_state;
      }
      if(Timer0_cnt &gt;= 600)
      {
            Timer0_cnt = 0;
            led2_state ^= 1;
            P01 = led2_state;
      }
      if(Timer0_cnt &gt;= 900)
      {
            Timer0_cnt = 0;
            led3_state ^= 1;
            P02 = led3_state;
      }
    }
}

void Timer0_Isr(void) interrupt 1
{
    for(i=0;i&lt;3;i++)
    {
      Timer0_cnt++;
    }
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300e9qz36y01thp1lc8.jpg" alt="" /></p>
<h2>6.2. <strong>任务2:</strong></h2>
<p><strong>数组点亮LED,实现流水灯。</strong></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

/*
    b0 b1         b7
    低            高
    LED0 ——   LED7
    0 1 1 1 1 1 1 1
    1 0 1 1 1 1 1 1
    1 1 0 1 1 1 1 1
    1 1 1 0 1 1 1 1
    1 1 1 1 0 1 1 1
    1 1 1 1 1 0 1 1
    1 1 1 1 1 1 0 1
    1 1 1 1 1 1 1 0
*/
uint8_t LED_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint16_t Timer0_cnt ={0,0,0};//定时器0任务周期时间数组
uint8_t i;

void Timer0_Init(void)                //1毫秒@40MHz
{
        TM0PS = 0x00;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
        TMOD &amp;= 0xF0;                        //设置定时器模式
        TL0 = 0xFB;                                //设置定时初始值
        TH0 = 0xF2;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

/******************** 主函数 **************************/
void main(void)
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
       //任务2
      if(Timer0_cnt &gt;= 500)
      {
         Timer0_cnt = 0;
         P0 = ~LED_State;
         if(++LED_pos &gt;= 8) LED_pos = 0;
      }
    }
}

void Timer0_Isr(void) interrupt 1
{
    for(i=0;i&lt;3;i++)
    {
      Timer0_cnt++;
    }
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300xfirf7rzs1zhrj79.jpg" alt="" /></p>
<h2>6.3. <strong>任务3:</strong></h2>
<p><strong>按键按下一次,LED通过数组移动一下。搭配定时器扫描消抖,不阻塞串口发送,串口稳定1s发一次。</strong></p>
<pre><code class="language-c">#include &quot;../COMM/AI8051U.h&quot;
#include &quot;../COMM/usb.h&quot;
#include &quot;stdio.h&quot;
#include &quot;intrins.h&quot;

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = &quot;@STCISP#&quot;;

//==========================================================================
void Delay20ms(void)        //@40MHz
{
        unsigned long edata i;

        _nop_();
        _nop_();
        i = 199998UL;
        while (i) i--;
}

/*
    b0 b1         b7
    低            高
    LED0 ——   LED7
    0 1 1 1 1 1 1 1
    1 0 1 1 1 1 1 1
    1 1 0 1 1 1 1 1
    1 1 1 0 1 1 1 1
    1 1 1 1 0 1 1 1
    1 1 1 1 1 0 1 1
    1 1 1 1 1 1 0 1
    1 1 1 1 1 1 1 0
*/
uint8_t LED_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint16_t Timer0_cnt ={0,0,0};//定时器0任务周期时间数组
uint8_t i;
uint8_t KEY_press = 0;//按键扫描消抖变量

void Timer0_Init(void)                //1毫秒@40MHz
{
        TM0PS = 0x00;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &amp;= 0x7F;                        //定时器时钟12T模式
        TMOD &amp;= 0xF0;                        //设置定时器模式
        TL0 = 0xFB;                                //设置定时初始值
        TH0 = 0xF2;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

/******************** 主函数 **************************/
void main(void)
{
    WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0xff;   //设置为推挽输出
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    P00 = 0;                //LED Power On

    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
       //任务3
      P0 = ~LED_State;
      
      if(Timer0_cnt &gt;= 1000)
      {
            Timer0_cnt = 0;
            printf(&quot;HELLO_AI8051U\r\n&quot;);
      }
      
      if(Timer0_cnt &gt;= 10)
      {
            Timer0_cnt = 0;
            if(P32 == 0)
            {
                KEY_press++;
                if(KEY_press &gt;= 10)
                {
                  KEY_press = 0;
                   if(++LED_pos &gt;= 8) LED_pos = 0;
                }
            }
            else
            {
                KEY_press = 0;
            }
      }
    }
}

void Timer0_Isr(void) interrupt 1
{
    for(i=0;i&lt;3;i++)
    {
      Timer0_cnt++;
    }
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300dxyy778x8js7w788.jpg" alt="" /><img src="data/attachment/forum/202412/16/160300q0nhbj9sibynz9ys.jpg" alt="" /></p>
<p><strong>工程中文文件名报错,修改为英文即可。</strong></p>
<p><img src="data/attachment/forum/202412/16/160300exj6q7b76murpqxq.jpg" alt="" /></p>
<h2>6.4. <strong>任务四:</strong></h2>
<p><strong>任务四是在任务一的基础上加了基于定时器0实现的多任务系统架构,使得代码更加简洁高效。</strong></p>
<pre><code class="language-c">#include &quot;system.h&quot;
#include &quot;task.h&quot;
/*
    b0 b1         b7
    低            高
    LED0 ——   LED7
    0 1 1 1 1 1 1 1
    1 0 1 1 1 1 1 1
    1 1 0 1 1 1 1 1
    1 1 1 0 1 1 1 1
    1 1 1 1 0 1 1 1
    1 1 1 1 1 0 1 1
    1 1 1 1 1 1 0 1
    1 1 1 1 1 1 1 0
*/
uint8_t LED_State = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//P0 LED控制数组
uint8_t LED_pos = 0;//LED控制数组索引
uint8_t i;

/******************** 主函数 **************************/
void main(void)
{
    System_Init();
    usb_init();                           //USB CDC 接口配置
    IE2 |= 0X80;                            //开启USB中断
    Timer0_Init();                        //定时器0初始化
    EA = 1;                                 //开启总中断

    while (DeviceState != DEVSTATE_CONFIGURED);   //等待USB完成配置

    while (1)
    {
      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            printf(&quot;hello mikeybie\r\n&quot;);
            usb_OUT_done();
      }
      Task_Callback_Handler();
    }
}

void Timer0_Isr(void) interrupt 1
{
    Task_Run_Time();
}
</code></pre>
<pre><code class="language-c">#include &quot;task.h&quot;
#include &quot;gpio.h&quot;

Task_Struct My_Task[]=
{
   {0,10,10,KEY_Task},
   {0,300,300,LED0_Blink},
   {0,600,600,LED1_Blink},
   {0,900,900,LED2_Blink},
};

uint8_t Task_Max = sizeof(My_Task)/sizeof(My_Task);

//任务状态标记函数,放在定时器1ms中断函数里面
void Task_Run_Time(void)
{
    uint8_t i;
    for(i=0;i&lt;Task_Max;i++)//扫描每一个任务列表
    {
       if(My_Task.tim_cnt)//任务执行周期有值
       {
         My_Task.tim_cnt--;
         if(My_Task.tim_cnt == 0)//任务执行周期到了
         {
            My_Task.tim_cnt = My_Task.tim_newcnt;//重新赋值周期
            My_Task.task_state = 1;//标记任务可执行状态
         }
       }
    }
}

//任务回调函数处理
void Task_Callback_Handler(void)
{
   uint8_t i;
   for(i=0;i&lt;Task_Max;i++)
   {
      if(My_Task.task_state)
      {
      My_Task.task_state = 0;
      My_Task.task_callback();
      }      
   }
}
</code></pre>
<pre><code class="language-c">#include &quot;gpio.h&quot;

uint8_t led0_state=0;
uint8_t led1_state=0;
uint8_t led2_state=0;

uint8_t KEY_press = 0;//按键扫描消抖变量

void LED0_Blink(void)
{
    led0_state ^= 1;
    P00 = led0_state;
}

void LED1_Blink(void)
{
    led1_state ^= 1;
    P01 = led1_state;
}

void LED2_Blink(void)
{
    led2_state ^= 1;
    P02 = led2_state;
}

void KEY_Task(void)
{
   if(P32 == 0)
   {
   KEY_press++;
   if(KEY_press &gt;= 10)
   {
         KEY_press = 0;
         printf(&quot;按键按下\r\n&quot;);
   }
   }
   else
   {
   KEY_press = 0;
   }
}
</code></pre>
<p><img src="data/attachment/forum/202412/16/160300t0opookyxzxy5zy8.jpg" alt="" /><img src="data/attachment/forum/202412/16/160300ybozbroommzjspdl.jpg" alt="" /></p>

mikeybie 发表于 2024-12-16 16:05:37

272761180 发表于 2024-12-16 12:29
贴主的笔记很详细,给你点个赞
希望你能继续坚持下去

谢谢

wamcncn 发表于 2024-12-16 16:30:41

KeilC251安装完,安装包按钮灰色啥原因

mikeybie 发表于 2024-12-16 16:40:07

wamcncn 发表于 2024-12-16 16:30
KeilC251安装完,安装包按钮灰色啥原因

?截图看看
页: [1] 2
查看完整版本: AI8051U学习打卡(一)