找回密码
 立即注册
楼主: yzhkpli

stc32g 9.4实验箱-冲哥教学视频学习笔记兼对比8051U实验箱学习

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2026-03-31 01:51:15

33

主题

176

回帖

2008

积分

金牌会员

积分
2008
发表于 昨天 15:01 | 显示全部楼层
使用 stc-isp软件生成的延时500ms的代码段

  1. void Delay500ms(void)        //@24.000MHz
  2. {
  3.         unsigned long edata i;
  4.         _nop_();
  5.         _nop_();
  6.         i = 2999998UL;
  7.         while (i) i--;
  8. }
复制代码


其中unsigned long edata i;去掉edata可否?
Qwen3-Coder
14:59:08
可以去掉 edata。 在这个特定的延时函数中,去掉 edata 对功能没有影响,反而是一种更标准和推荐的写法。
为什么可以去掉 edata?
1-edata 的含义:edata 是 Keil C51 编译器的一个扩展关键字,用于指定变量存储在 外部数据存储区 (External Data Area) 的低128字节(地址 0x0000 - 0x00FF)。这个区域可以通过 MOVX @R0 或 MOVX @R1 指令进行寻址,速度比访问高地址的 xdata 区域快。
2-idata vs data:在8051架构中,变量默认存储在 内部数据存储区 (Internal Data Area, idata),也就是片内的 RAM(通常是地址 0x00 - 0xFF)。访问 idata 是最快的。
3-变量的生命周期和作用域:在 Delay500ms 函数中,变量 i 是一个局部变量。在函数被调用时,它会在栈上分配空间(通常在 idata 区)。当函数结束时,它的生命周期也随之结束。edata 关键字在这里并没有实际意义,因为编译器会自动将局部变量分配到最适合的位置(通常是 idata)。
4-编译器行为:现代C51编译器(如 Keil C51)对于这种简单的局部变量,通常会自动将其优化到 idata 区或直接放入寄存器中,以获得最佳性能。强制指定 edata 反而可能阻止这种优化。




在循环中设置延时
  1. <div>while(1){
  2. <span style="white-space:pre">        </span>P40=0;//这句可以放在循环之前
  3. <span style="white-space:pre">        </span>P60=0;P67=0;Delay500ms();
  4. <span style="white-space:pre">        </span>P60=1;P67=1;Delay500ms();
  5. }</div>
复制代码




回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2026-03-31 01:51:15

33

主题

176

回帖

2008

积分

金牌会员

积分
2008
发表于 昨天 16:34 | 显示全部楼层
2. 函数的使用
在模块化编程里,函数使用分为如下三步:
函数定义
        返回值 函数名称(入口参数)
        {
                函数要执行的功能
        }
        @返回值:没有返回值就是void
        @函数名称:避开关键词,不重复,非特殊字符随便取
        @入口参数:类型 + 名称,多个参数用 “,” 分开,空就写void
函数声明
        返回值 函数名称(入口参数);
函数调用
        函数名称(入口参数);

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2026-03-31 01:51:15

33

主题

176

回帖

2008

积分

金牌会员

积分
2008
发表于 昨天 16:38 | 显示全部楼层
3. 新建文件,使用模块化编程
新建xxx.c和xxx.h文件,代表一个功能块。
xxx.h 格式:

        #ifndef __XXX_H
        #define __XXX_H

        // 调用头文件
        // 函数声明...

        #endif
xxx.c 格式:

        #include "xxx.h"

        // 函数定义

注意:添加文件一定要记得引用路径和添加到工程里。

qwen给出的例子
1. 创建 delay.h 文件
        这个头文件 (delay.h) 定义了延时模块对外的接口(即函数声明),方便其他 .c 文件调用。

// delay.h
#ifndef __DELAY_H
#define __DELAY_H

// ============= 调用头文件 =============
// 本模块不需要额外的头文件,因为它只定义了一个函数
// 如果其他模块需要使用STC32G的寄存器,才需要包含"stc32g.h"
// #include "stc32g.h" // 此处不需要


// ============= 宏定义 =============
// 定义主时钟频率,方便在不同频率下调整延时参数
// 注意:如果在其他文件中也需要这个宏,可以将其移到一个公共的config.h文件中
#define MAIN_Fosc    24000000UL


// ============= 函数声明 =============
// 声明延时函数,供其他模块调用
void Delay500ms(void);

// 如果以后增加其他延时函数,也在这里声明
// void DelayMs(unsigned int ms); // 例如:毫秒级延时
// void DelayUs(unsigned int us); // 例如:微秒级延时

#endif // __DELAY_H


2. 创建 delay.c 文件
这个源文件 (delay.c) 包含了 delay.h 中声明的函数的具体实现(即函数定义)。

// delay.c
// ============= 包含头文件 =============
#include "delay.h"      // 必须首先包含对应的头文件
#include "stc32g.h"     // 因为函数体内使用了_nop_()指令,需要包含STC32G的头文件


// ============= 函数定义 =============
/**
* @brief  延时函数,基于24MHz时钟,延时约500毫秒
* @param  void
* @retval void
*/
void Delay500ms(void)
{
    // 定义一个无符号长整型变量i作为循环计数器
    // 去掉 'edata' 关键字,使用默认存储类型,更标准、更高效
    unsigned long i;

    // 执行两条空指令,用于微调延时时间
    _nop_();
    _nop_();

    // 设置循环次数,该数值是根据目标延时和时钟频率计算得出的
    i = 2999998UL;

    // 通过一个空的while循环消耗CPU时钟周期,从而实现延时
    while (i--)
    {
        ; // 空语句
    }
}

// 如果在delay.h中声明了其他函数,它们的定义也写在这里
// void DelayMs(unsigned int ms) { ... }
// void DelayUs(unsigned int us) { ... }

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2026-03-31 01:51:15

33

主题

176

回帖

2008

积分

金牌会员

积分
2008
发表于 昨天 17:03 | 显示全部楼层
对项目进行了修改,把delay.h和delay.c放入了COMM文件夹中。
main.c改成了
  1. #include "./COMM/stc.h"
  2. #include "./COMM/delay.h"
  3. #define MAIN_Fosc    24000000UL
  4. void sys_init();
  5. //void Delay500ms(void);
  6. void main(void)
  7. {
  8.         sys_init();
  9.         P40=0;
  10.         while(1){
  11.                 //codes
  12.                 P60=0;P62=0;P61=1;P63=1;
  13.                 Delay500ms();
  14.                 P60=1;P62=1;P61=0;P63=0;
  15.                 Delay500ms();               
  16.         }
  17. }
  18. void sys_init()
  19. {
  20.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  21.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  22.     CKCON = 0; //提高访问XRAM速度
  23.             P_SW2 |= 0x80;                //B7位写1,使能访问XFR
  24.     P0M1 = 0x00;   P0M0 = 0x00;
  25.     P1M1 = 0x00;   P1M0 = 0x00;
  26.     P2M1 = 0x00;   P2M0 = 0x00;
  27.     P3M1 = 0x00;   P3M0 = 0x00;
  28.     P4M1 = 0x00;   P4M0 = 0x00;
  29.     P5M1 = 0x00;   P5M0 = 0x00;
  30.     P6M1 = 0x00;   P6M0 = 0x00;
  31.     P7M1 = 0x00;   P7M0 = 0x00;
  32. }       
  33. //void Delay500ms(void)        //@24.000MHz
  34. //{
  35. //        u32 i;
  36. //        _nop_();
  37. //        _nop_();
  38. //        i = 2999998UL;
  39. //        while (i) i--;
  40. //}
复制代码



COMM/delay.h内容
  1. // delay.h
  2. #ifndef __DELAY_H
  3. #define __DELAY_H
  4. // ============= 调用头文件 =============
  5. // 本模块不需要额外的头文件,因为它只定义了一个函数
  6. // 如果其他模块需要使用STC32G的寄存器,才需要包含"stc32g.h"
  7. // #include "stc32g.h" // 此处不需要
  8. // ============= 宏定义 =============
  9. // 定义主时钟频率,方便在不同频率下调整延时参数
  10. // 注意:如果在其他文件中也需要这个宏,可以将其移到一个公共的config.h文件中
  11. #define MAIN_Fosc    24000000UL
  12. // ============= 函数声明 =============
  13. // 声明延时函数,供其他模块调用
  14. void Delay500ms(void);
  15. // 如果以后增加其他延时函数,也在这里声明
  16. // void DelayMs(unsigned int ms); // 例如:毫秒级延时
  17. // void DelayUs(unsigned int us); // 例如:微秒级延时
  18. #endif // __DELAY_H
复制代码


COMM.delay.c内容
  1. // delay.c
  2. // ============= 包含头文件 =============
  3. #include "delay.h"      // 必须首先包含对应的头文件
  4. #include "stc32g.h"     // 因为函数体内使用了_nop_()指令,需要包含STC32G的头文件
  5. // ============= 函数定义 =============
  6. /**
  7. * @brief  延时函数,基于24MHz时钟,延时约500毫秒
  8. * @param  void
  9. * @retval void
  10. */
  11. void Delay500ms(void)
  12. {
  13.     // 定义一个无符号长整型变量i作为循环计数器
  14.     // 去掉 'edata' 关键字,使用默认存储类型,更标准、更高效
  15.     unsigned long i;
  16.     // 执行两条空指令,用于微调延时时间
  17.     _nop_();
  18.     _nop_();
  19.     // 设置循环次数,该数值是根据目标延时和时钟频率计算得出的
  20.     i = 2999998UL;
  21.     // 通过一个空的while循环消耗CPU时钟周期,从而实现延时
  22.     while (i--)
  23.     {
  24.         ; // 空语句
  25.     }
  26. }
  27. // 如果在delay.h中声明了其他函数,它们的定义也写在这里
  28. // void DelayMs(unsigned int ms) { ... }
  29. // void DelayUs(unsigned int us) { ... }
复制代码


记得把delay.c也add进入项目,编译通过



以上已经在26-03-31晚上烧写通过。

06_led_flash_01.zip

85.03 KB, 下载次数: 1

建立了简单目录结构的led闪烁程序

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2026-03-31 01:51:15

33

主题

176

回帖

2008

积分

金牌会员

积分
2008
发表于 15 分钟前 | 显示全部楼层
今天折腾一大顿终于让stc32g 9.4实验箱通过一箭双雕烧写程序了。(实验箱和一箭双雕都没坏,是电脑的程序有了问题,装了mpython alpha版本,卸载后恢复正常了)

printf程序有了问题。
  1. #include "stc32g.h"
  2. #include "STC32_STC8_USB.h"
  3. void sys_init();
  4. void main()
  5. {
  6.                 //USER_STCISPCMD = "@STCISP#";
  7.     sys_init();
  8.                 usb_init();//该函数声明在stc32_stc8_usb.h中,定义在stc_usb_hid_32g.LIB中
  9.                 EA=1;
  10.        
  11. // 注册回调函数(这行代码“调用”了 set_usb_IN_callback)
  12. //   set_usb_IN_callback(my_usb_in_callback);
  13. //// 例如,通过函数调用来设置ISP命令
  14. //    set_usb_ispcmd("@MY_CUSTOM_ISP_COMMAND#");
  15.     while (1)
  16.     {
  17. //                        if(DeviceState != DEVSTATE_CONFIGURED)
  18. //                                continue;
  19.                         if(DeviceState == DEVSTATE_CONFIGURED){
  20.                                         if (bUsbOutReady)
  21.                                         {
  22.                                                 usb_OUT_done();   //接收应答(固定格式)
  23.                                                 //常规用法:
  24.                                                 printf("Hello World!");
  25.                                                 printf("室内温度:%.2f\r\n", 11.2);
  26.                                         }
  27.                                         P40=0;
  28.                                         P60=0;
  29.                                         P62=0;
  30.                         }else{
  31.             int i;
  32.             for(i=0; i<50000; i++); // 空循环,消耗时间
  33.             
  34.             P40 = ~P40; // 反转P40状态,实现闪烁
  35.             P60 = 1; // 熄灭其他LED
  36.             P62 = 1; // 熄灭其他LED                       
  37.                         }
  38.     }
  39. }
  40. void sys_init()
  41. {
  42.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  43.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  44.     CKCON = 0; //提高访问XRAM速度
  45.     P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
  46.     P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
  47.     P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
  48.     P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
  49.     P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
  50.     P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
  51.     P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
  52.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  53.           //设置USB使用的时钟源
  54.     IRC48MCR = 0x80;    //使能内部48M高速IRC
  55.     while (!(IRC48MCR & 0x01));  //等待时钟稳定
  56. }
复制代码

结果连led都不闪!!真是莫名其妙

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-31 22:47 , Processed in 0.111143 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表