laohu_zhou 发表于 2025-6-18 12:29:18

学习感悟之实战:第八集 定时器周期性调度任务-结构体数组的周期性任务调度

通过这1小时23分钟的超长视频学习,认识到需要学习的内容太多,需要更多时间的消化,感谢冲哥,大半夜的录视频教学。
主程序代码简洁多了:
#include "config.h"            //调用头文件,""本工程文件目录下
#include "task.h"
#include "io.h"


char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";

void main(void)
{

    Sys_init();
    usb_init();   //USB CDC 接口配置 初始化
   
    IE2 |= 0x80;    //使能USB中断
    Timer0_Init();//定时器初始化
    EA = 1;         //开启总中断
    while (DeviceState != DEVSTATE_CONFIGURED);//等待USB完成配置   
   
    while(1)
    {
      if (bUsbOutReady)
      {
            //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            //printf("P2%d\r\n",num); //%字符的格式含义:%s把后面""内的字符替换,\r\n为输出自动换行
            usb_OUT_done();
      }

      Task_Pro_Handler_Callback();                                //执行功能函数

    }
}



void Timer0_Isr(void) interrupt 1                //1MS执行一次
{
        Task_Marks_Handler_Callback();                                        //系统计时
}

laohu_zhou 发表于 2025-6-21 13:01:05

【重做三个实验之一】AiCube 实验一:直接 printf_usb("Hello World !\r\n")
                        32位8051单片机入门的第一个完整的C语言程序

今天有最新版的AIapp-ISP-V6.95V 下载,开始AiCube生成完整的C语言程序,真的是太方便啦,是我们初学者的福音。

//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
//   1. (2025-06-21) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"                     //默认已包含stdio.h、intrins.h、ai_usb.h等头文件


//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>


//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>




////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
//      USBLIB_OUT_Done();            //查询方式处理USB接收的数据
      printf_usb("Hello World!~o~laohu_zhou\r\n");
      //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
      // 在此添加主函数中用户主循环代码
      //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}

////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
    EnableAccessXFR();                  //使能访问扩展XFR
    AccessCodeFastest();                //设置最快速度访问程序代码
    AccessIXramFastest();               //设置最快速度访问内部XDATA
    IAP_SetTimeBase();                  //设置IAP等待参数,产生1us时基

    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口为准双向口模式

    CLK_Init();                         //时钟模块初始化
    USBLIB_Init();                      //USB库初始化

    //<<AICUBE_USER_INITIAL_CODE_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_INITIAL_CODE_END>>

    EnableGlobalInt();                  //使能全局中断
}

////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
    do
    {
      NOP(34);                        //(MAIN_Fosc + 500000) / 1000000 - 6
    } while (--us);
}


////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
    uint16_t i;

    do
    {
      i = MAIN_Fosc / 6000;
      while (--i);
    } while (--ms);
}


////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
    CLK_SYSCLK_Divider(10);             //切换主时钟前先将系统时钟降频

    HIRC_40M();                         //选择内部预置的频率

    CLK_MCLK_HIRC();                  //选择内部高精度HIRC作为主时钟
    CLK_MCLK2_BYPASS();               //旁路MCLK2,直接使用MCLK选择

    CLK_SYSCLK_Divider(1);            //设置系统时钟分频系数

    CLK_HSIOCK_MCLK();                  //选择MCLK主时钟作为高速外设时钟源
    CLK_HSIOCK_Divider(1);            //设置高速外设时钟预分频系数

    CLK_SPICLK_Divider(1);            //设置SPI时钟预分频系数
    CLK_I2SCLK_Divider(1);            //设置I2S时钟预分频系数
    CLK_PWMACLK_Divider(1);             //设置PWMA时钟预分频系数
    CLK_PWMBCLK_Divider(1);             //设置PWMB时钟预分频系数
    CLK_TFPUCLK_Divider(1);             //设置TFPU时钟预分频系数

    //<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_CLOCK_INITIAL_END>>
}

////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
    usb_init();                         //初始化USB模块
    USB_SetIntPriority(0);            //设置中断为最低优先级
    set_usb_ispcmd("@STCISP#");         //设置USB不停电下载命令

    //<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_USBLIB_INITIAL_END>>
}

////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
    while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
      WDT_Clear();                  //清看门狗定时器 (防止硬件自动使能看门狗)
}

////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
    if (bUsbOutReady)                   //查询是否有接收到USB主机发送数据
    {
      //<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
      // 在此添加中断函数用户代码
      USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
                                        //在此处添加用户处理接收数据的代码
      //<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
      usb_OUT_done();               //当前包的数据处理完成,通知USB主机可以发送下一包数据
    }
}


//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>



laohu_zhou 发表于 2025-6-21 21:19:49

【重做三个实验之二】AiCube 实验二:查询方式,查询到电脑命令后,
                           printf_usb("Hello World !\r\n")

这次的实验与上一个的实验相比,除了查询方式处理命令之外,在AiCube项目创建助手的“新建AiCube项目”的“项目文件类型”勾选了“多代码文件项目”,生成的main.c主程序代码简洁多了
main.c:
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
//   1. (2025-06-21) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"                     //默认已包含stdio.h、intrins.h、ai_usb.h等头文件


//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>


//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>



////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
      USBLIB_OUT_Done();            //查询方式处理USB接收的数据

      //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
      // 在此添加主函数中用户主循环代码

      if (bUsbOutReady)
      {
//            USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
            if (UsbOutBuffer == 6)
            printf_usb("Hello World!~o~laohu_zhou\r\n");//如果接收到6,就打印Hello World!~o~laohu_zhou
            else
                if (UsbOutBuffer == 7)
                printf_usb("China!~o~laohu_zhou\r\n");//如果接收到7,就打印China!~o~laohu_zhou
         }
      //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}

////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
    EnableAccessXFR();                  //使能访问扩展XFR
    AccessCodeFastest();                //设置最快速度访问程序代码
    AccessIXramFastest();               //设置最快速度访问内部XDATA
    IAP_SetTimeBase();                  //设置IAP等待参数,产生1us时基

    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口为准双向口模式

    CLK_Init();                         //时钟模块初始化
    USBLIB_Init();                      //USB库初始化

    //<<AICUBE_USER_INITIAL_CODE_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_INITIAL_CODE_END>>

    EnableGlobalInt();                  //使能全局中断
}

////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
    do
    {
      NOP(34);                        //(MAIN_Fosc + 500000) / 1000000 - 6
    } while (--us);
}


////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
    uint16_t i;

    do
    {
      i = MAIN_Fosc / 6000;
      while (--i);
    } while (--ms);
}


//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>



laohu_zhou 发表于 7 天前

【重做三个实验之三】 中断方式,单片机USB中断接收服务函数收到命令后,
                           printf_usb("Hello World !\r\n")

AiCube工具真的是太方便了,希望STC能够继续完善,并支持以前生产的单片机。
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
//   1. (2025-06-22) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"                     //默认已包含stdio.h、intrins.h、ai_usb.h等头文件


//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>


//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>




////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
      //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
      // 在此添加主函数中用户主循环代码
      //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}

////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
    EnableAccessXFR();                  //使能访问扩展XFR
    AccessCodeFastest();                //设置最快速度访问程序代码
    AccessIXramFastest();               //设置最快速度访问内部XDATA
    IAP_SetTimeBase();                  //设置IAP等待参数,产生1us时基

    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口为准双向口模式

    USBLIB_Init();                      //USB库初始化

    //<<AICUBE_USER_INITIAL_CODE_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_INITIAL_CODE_END>>

    EnableGlobalInt();                  //使能全局中断
}

////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
    do
    {
      NOP(34);                        //(MAIN_Fosc + 500000) / 1000000 - 6
    } while (--us);
}


////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
    uint16_t i;

    do
    {
      i = MAIN_Fosc / 6000;
      while (--i);
    } while (--ms);
}


////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
    usb_init();                         //初始化USB模块
    USB_SetIntPriority(3);            //设置中断为最高优先级
    set_usb_OUT_callback(USBLIB_OUT_Callback); //设置USB中断回调函数
    set_usb_ispcmd("@STCISP#");         //设置USB不停电下载命令

    //<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_USBLIB_INITIAL_END>>
}

////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
    while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
      WDT_Clear();                  //清看门狗定时器 (防止硬件自动使能看门狗)
}

////////////////////////////////////////
// USB设备接收数据中断回调程序
// 入口参数: 无
// 函数返回: 无
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Callback(void)
{
    //<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码
    USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
                                        //在此处添加用户处理接收数据的代码
    if (UsbOutBuffer == 6)
      printf_usb("Hello World !^o^laohu_zhou\r\n");      //接收到数据6后打印“Hello World !^o^laohu_zhou”
    else if (UsbOutBuffer == 7)
      printf_usb("China !^o^laohu_zhou\r\n");                //接收到数据7后打印“China !^o^laohu_zhou”
    //<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
}


//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>

laohu_zhou 发表于 3 天前

收到了实验箱,感谢司经理的热心帮助。
实验箱主控芯片AI8051U,做工不错,就是感觉盒子有点厚。
继续打卡学习冲哥的视频实验。

laohu_zhou 发表于 3 天前

实验箱接上usb电源就是时钟显示,加入两个按键调节,不做实验的时候就下载时钟程序做时钟用,真好。

国学芯用 发表于 3 天前

建议可以做下面这3个最简单的程序





【新提醒】还是从 printf_usb("Hello World !\r\n") 开始,《单片机原理及应用》入门@Ai8051U - 51 发烧友,UAC,极致音频,大国工匠,艺术人生,乐林漫步 国芯技术交流网站 - AI32位8051交流社区

laohu_zhou 发表于 3 天前

已经做过了{:4_202:}
页: 1 [2]
查看完整版本: 以擎天柱核心功能实验板学习打卡《8051U深度入门到32位51大型实战教学视频》