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

AI8051U学习心得-1

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 12:30:10 | 显示全部楼层
vdgh*** 发表于 2026-1-2 12:27
学习心得-6  运用定时器执行双灯轮巡点亮

执行代码后现象

VID_20260102_122824.mp4

1.41 MB, 下载次数: 0

程序现象演示

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 12:59:34 | 显示全部楼层
学习心得-7 数码管模拟测试,成功点亮数码管

  1. #include "io.h"
  2. u8 SEG_NUM[]=
  3. {
  4.     0x3F,       /*'0', 0*/
  5.     0x06,       /*'1', 1*/
  6.     0x5B,       /*'2', 2*/
  7.     0x4F,       /*'3', 3*/
  8.     0x66,       /*'4', 4*/
  9.     0x6D,       /*'5', 5*/
  10.     0x7D,       /*'6', 6*/
  11.     0x07,       /*'7', 7*/
  12.     0x7F,       /*'8', 8*/
  13.     0x6F,       /*'9', 9*/
  14.     0x77,       /*'A', 10*/
  15.     0x7C,       /*'B', 11*/
  16.     0x39,       /*'C', 12*/
  17.     0x5E,       /*'D', 13*/
  18.     0x79,       /*'E', 14*/
  19.     0x71,       /*'F', 15*/
  20.     0x40,       /*'-', 16*/
  21.     0x00,       /*' ', 17*/
  22.     0x80,       /*'.', 18*/
  23. };
  24. u8 T_NUM[8] =
  25. {
  26.         0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80
  27. };
  28. u8 State1 = 0;                                        //LED1初始状态
  29. u8 State2 = 0;                                        //LED2初始状态
  30. u8 State3 = 0;                                        //LED3初始状态
  31. u16 Key_Vol[3] ;                                //按键按下持续时间
  32. u8 Key_flag = 0;               
  33. u8 cnt[3];
  34. void LED0_Blink(void)
  35. {
  36.         State1 = !State1;
  37.         P20 = State1;
  38. }
  39. void LED1_Blink(void)
  40. {
  41.         State2 = !State2;
  42.         P21 = State2;
  43. }
  44. void LED2_Blink(void)
  45. {
  46.         State3 = !State3;
  47.         P22 = State3;
  48. }
  49. void KEY_Task(void)
  50. {
  51.         if( P32 == 0 )
  52.         {
  53.                 Key_Vol[0]++;
  54.                 if( Key_Vol[0]==5 )
  55.                 {
  56.                         //按键按下的任务
  57.             Key_flag = !Key_flag;
  58.             if(cnt[2])
  59.             {
  60.               cnt[1] = 0;
  61.               cnt[2] = 0;
  62.             }
  63.                         printf( "按键单击\r\n" );
  64.                 }
  65.         }
  66.         else
  67.         {
  68.                 Key_Vol[0] = 0;
  69.         }
  70. }
  71.         
  72. u8 shi  =0;
  73. u8 fen  =0;
  74. u8 miao =0;
  75. //void TIMECOUNT_Task(void)
  76. //{
  77. //        miao ++;
  78. //        if( miao>59 )
  79. //        {
  80. //                miao = 0;
  81. //                fen++;
  82. //                if( fen>59 )
  83. //                {
  84. //                        fen = 0;
  85. //                        shi ++;
  86. //                        if( shi>23 )
  87. //                                shi = 0;
  88. //                }
  89. //        }
  90. //}
  91. u8 state_now = 0;
  92. void PLED_40(void)
  93. {
  94.         u8 cod[8];
  95.         cod[0] = 0x0f;                //表示开启P0-P3
  96.         cod[1] = 0X01;                //P0端口        
  97.         cod[2] = 0X01;                //P1
  98.         cod[3] = ~T_NUM[state_now];                //P2
  99.         cod[4] = 0X01;                //P3
  100.         LED40_SendData( cod,5 );
  101.         
  102.         P2 = ~T_NUM[state_now];
  103.         
  104.         state_now++;
  105.         if( state_now>7 )
  106.                 state_now = 0;
  107. }
  108. void SEG_PC( void )
  109. {
  110.         u8 cod[8];
  111.         
  112.         cod[0] = SEG_NUM[shi/10];                                        //小时的十位数的数码管段码
  113.         cod[1] = SEG_NUM[shi%10];
  114.         cod[2] =SEG_NUM[16];                                                //数码管刷段码和位码
  115.         cod[3] = SEG_NUM[fen/10];                                        //分钟
  116.         cod[4] = SEG_NUM[fen%10];
  117.         cod[5] =SEG_NUM[16];                                                //数码管刷段码和位码        
  118.         cod[6] = SEG_NUM[miao/10];                                        //分钟
  119.         cod[7] = SEG_NUM[miao%10];
  120.         
  121.         SEG7_ShowCode(cod);
  122.         miao ++;
  123.         if( miao>59 )
  124.         {
  125.                 miao = 0;
  126.                 fen++;
  127.                 if( fen>59 )
  128.                 {
  129.                         fen = 0;
  130.                         shi ++;
  131.                         if( shi>23 )
  132.                                 shi = 0;
  133.                 }
  134.         }   
  135. }
  136. // 课后小练:简易免单器
  137. void SEGLED_PC(void)
  138. {
  139.         u8 cod[8];
  140.     if(Key_flag)
  141.     {
  142.         cod[0] = SEG_NUM[1];                                       
  143.         cod[1] = SEG_NUM[0]|SEG_NUM[18];
  144.         cod[2] = SEG_NUM[0];                                                
  145.         cod[3] = SEG_NUM[0];        
  146.         cod[4] = SEG_NUM[cnt[1]/10];
  147.         cod[5] = SEG_NUM[cnt[1]%10]|SEG_NUM[18];                                       
  148.         cod[6] = SEG_NUM[cnt[0]/10];                                       
  149.         cod[7] = SEG_NUM[cnt[0]%10];        
  150.     }
  151.     else
  152.     {
  153.         cod[0] = SEG_NUM[1];                                       
  154.         cod[1] = SEG_NUM[0]|SEG_NUM[18];
  155.         cod[2] = SEG_NUM[0];                                                
  156.         cod[3] = SEG_NUM[0];
  157.         
  158.         cod[4] = SEG_NUM[cnt[1]/10];
  159.         cod[5] = SEG_NUM[cnt[1]%10]|SEG_NUM[18];                                       
  160.         cod[6] = SEG_NUM[cnt[0]/10];                                       
  161.         cod[7] = SEG_NUM[cnt[0]%10];
  162.         }
  163.         SEG7_ShowCode(cod);
  164.    
  165.     if(!cnt[2] && Key_flag)
  166.     {
  167.          cnt[0]++;
  168.          if(cnt[0] > 59)
  169.          {
  170.                 cnt[0] = 0;
  171.                 cnt[1]++;
  172.                 if( cnt[1]>9 )
  173.                 {
  174.             cnt[2] = 1;
  175.                 }
  176.          }   
  177.     }
  178. }
复制代码
IMG_20260102_125659.jpg
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 13:10:42 | 显示全部楼层
核心板 学习心得-8  PWM输出   p20-p23输出不同位数的占空比,led点亮成功。看实物有呼吸灯效果。
  1. #include "..\..\comm\AI8051U.h"
  2. #include "intrins.h"
  3. typedef     unsigned char   u8;
  4. typedef     unsigned int    u16;
  5. typedef     unsigned long   u32;
  6. #define     MAIN_Fosc       24000000UL  // 定义主时钟
  7. #define     Timer0_Reload   (65536UL - (MAIN_Fosc / 12 / 400)) // Timer0中断频率400Hz
  8. #define PCA0      0
  9. #define PCA1      1
  10. #define PCA2      2
  11. #define PCA3      3
  12. bit B_PWM0_Dir, B_PWM1_Dir, B_PWM2_Dir, B_PWM3_Dir; // 方向标志
  13. u16 pwm0, pwm1, pwm2, pwm3;
  14. void Timer0_config(void);
  15. void PWM_config(void);
  16. void UpdatePwm(u8 PCA_id, u16 pwm_value);
  17. void main() {
  18.     WTST = 0;  // 最快指令执行速度
  19.     EAXFR = 1; // 扩展寄存器访问使能
  20.     CKCON = 0; // 提高XRAM访问速度
  21.     // 端口初始化为准双向口
  22.     P2M1 = P2M0 = 0x00;
  23.     P2M1 = P2M1 = 0x00;
  24.     P2 &= 0x00; // 清除P2口输出
  25.     Timer0_config();
  26.     PWM_config();
  27.     EA = 1;      // 开启总中断
  28.     // 初始化PWM值及方向
  29.     pwm0 = 128; B_PWM0_Dir = 0; UpdatePwm(PCA0, pwm0);
  30.     pwm1 = 512; B_PWM1_Dir = 0; UpdatePwm(PCA1, pwm1);
  31.     pwm2 = 32;  B_PWM2_Dir = 0; UpdatePwm(PCA2, pwm2);
  32.     pwm3 = 256; B_PWM3_Dir = 0; UpdatePwm(PCA3, pwm3);
  33.     while (1);
  34. }
  35. // Timer0初始化:12T模式,自动重载
  36. void Timer0_config(void) {
  37.     AUXR &= ~0x80;   // 清除第7位,设置Timer0为12T模式
  38.     TH0 = (u8)(Timer0_Reload >> 8);
  39.     TL0 = (u8)(Timer0_Reload & 0xFF);
  40.     ET0 = 1;         // 使能Timer0中断
  41.     TR0 = 1;         // 启动Timer0
  42. }
  43. // PWM初始化配置
  44. void PWM_config(void) {
  45.     CMOD = (CMOD & ~0xC0) | (2 << 5); // 选择PCA通道映射到P2.0-P2.3
  46.     CCON |= 0x40;                     // 启动PCA定时器
  47.     // PCA0: 8位PWM,P2.0
  48.     CCAPM0 = 0x42;                    // PWM模式
  49.     PCA_PWM0 = 0x08;                  // 8位PWM,ECOMD=0, TOGBIT=0
  50.     CCAP0H = 0x80;                    // 初始占空比50%
  51.     // PCA1: 10位PWM,P2.1
  52.     CCAPM1 = 0x42;                    // PWM模式
  53.     PCA_PWM1 = 0x0A;                  // 10位PWM,ECOMD=0, TOGBIT=0
  54.     CCAP1H = 0x80 >> 2;               // 高8位初始值 (1024/4=256)
  55.     CCAP1L = (0x80 & 0x03) << 6;      // 低2位初始值
  56.     // PCA2: 6位PWM,P2.2
  57.     CCAPM2 = 0x42;                    // PWM模式
  58.     PCA_PWM2 = 0x09;                  // 6位PWM,ECOMD=0, TOGBIT=0
  59.     CCAP2H = 0x20;                    // 初始占空比 (64/64=31.25%)
  60.     // PCA3: 8位PWM,P2.3
  61.     CCAPM3 = 0x42;                    // PWM模式
  62.     PCA_PWM3 = 0x08;                  // 8位PWM,ECOMD=0, TOGBIT=0
  63.     CCAP3H = 0x80;                    // 初始占空比50%
  64. }
  65. // 更新PWM占空比
  66. void UpdatePwm(u8 PCA_id, u16 pwm_value) {
  67.     switch (PCA_id) {
  68.         case PCA0: // 8位PWM
  69.             CCAP0H = (u8)pwm_value;
  70.             break;
  71.         case PCA1: // 10位PWM
  72.             CCAP1H = (u8)(pwm_value >> 2);  // 高8位
  73.             CCAP1L = (u8)((pwm_value & 0x03) << 6); // 低2位左移6位
  74.             break;
  75.         case PCA2: // 6位PWM
  76.             CCAP2H = (u8)(pwm_value & 0x3F); // 低6位
  77.             break;
  78.         case PCA3: // 8位PWM
  79.             CCAP3H = (u8)pwm_value;
  80.             break;
  81.     }
  82. }
  83. // Timer0中断服务例程
  84. void timer0(void) interrupt 1 {
  85.     // PCA0: 8位PWM
  86.     if (B_PWM0_Dir) {
  87.         if (--pwm0 <= 1) B_PWM0_Dir = 0;
  88.     } else {
  89.         if (++pwm0 >= 255) B_PWM0_Dir = 1;
  90.     }
  91.     UpdatePwm(PCA0, pwm0);
  92.     // PCA1: 10位PWM
  93.     if (B_PWM1_Dir) {
  94.         if (--pwm1 <= 1) B_PWM1_Dir = 0;
  95.     } else {
  96.         if (++pwm1 >= 1023) B_PWM1_Dir = 1;
  97.     }
  98.     UpdatePwm(PCA1, pwm1);
  99.     // PCA2: 6位PWM
  100.     if (B_PWM2_Dir) {
  101.         if (--pwm2 <= 1) B_PWM2_Dir = 0;
  102.     } else {
  103.         if (++pwm2 >= 63) B_PWM2_Dir = 1;
  104.     }
  105.     UpdatePwm(PCA2, pwm2);
  106.     // PCA3: 8位PWM
  107.     if (B_PWM3_Dir) {
  108.         if (--pwm3 <= 1) B_PWM3_Dir = 0;
  109.     } else {
  110.         if (++pwm3 >= 255) B_PWM3_Dir = 1;
  111.     }
  112.     UpdatePwm(PCA3, pwm3);
  113. }
复制代码
IMG_20260102_130933.jpg
IMG_20260102_130936.jpg
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 13:21:28 | 显示全部楼层
学习心得9-p2端口流水灯,测试成功

  1. /**************************************************************
  2. * 程序功能:STC擎天柱核心板 P2端口 流水灯
  3. * 描述:P2端口的8个LED灯依次循环点亮,形成流水效果。
  4. **************************************************************/
  5. #include <AI8051U.H>      // 包含擎天柱核心板(AI8051U)的寄存器定义头文件
  6. #include <intrins.h>      // 包含C51编译器的内部函数库,例如_crol_循环移位函数
  7. // 定义主时钟频率,用于精确计算延时
  8. #define                MAIN_Fosc        24000000UL  // 定义主时钟频率为24MHz (UL表示无符号长整型)
  9. /**
  10. * @brief 毫秒级延时函数 (软件延时)
  11. * @param ms 需要延时的毫秒数
  12. * @note 此函数的延时精度依赖于CPU主时钟频率(MAIN_Fosc)。
  13. *       当时钟频率改变时,需要重新计算或调整延时参数。
  14. */
  15. void delay_ms(unsigned char ms)
  16. {
  17.         unsigned int i;
  18.     // 外层循环,控制总的毫秒数
  19.         do
  20.         {
  21.         // 内层循环,实现大约1毫秒的延时
  22.         // MAIN_Fosc / 6000: 这个计算基于标准8051架构,一个机器周期 = 12个时钟周期。
  23.         // 但STC15/STC32系列单片机可以设置为1T模式,一个机器周期 = 1个时钟周期。
  24.         // 这里的计算方式比较特殊,可能是在特定时钟模式下的经验值,目的是让内部while循环执行时间约为1ms。
  25.                 i = MAIN_Fosc / 6000;
  26.                 while(--i); // 空循环,通过消耗CPU时间来实现延时
  27.         }
  28.         while(--ms); // 外层循环,每执行一次,ms减1,直到ms为0
  29. }
  30. /**
  31. * @brief 系统初始化函数
  32. */
  33. void Init(void)
  34. {
  35.         WTST = 0;                                        // 设置程序指令等待参数,0为最快速度,不等待
  36.         EAXFR = 1;                                        // 使能访问扩展RAM(XFR),这是操作P4-P7端口的前提
  37.         CKCON = 0;                                        // 设置外部RAM访问时序,0为标准时序
  38.         // 将所有GPIO端口设置为准双向口模式,这是最通用的I/O模式
  39.         P0M1 = 0x00;        P0M0 = 0x00;        // P0口设置为准双向口
  40.         P1M1 = 0x00;        P1M0 = 0x00;        // P1口设置为准双向口
  41.         P2M1 = 0x00;        P2M0 = 0x00;        // P2口设置为准双向口
  42.         P3M1 = 0x00;        P3M0 = 0x00;        // P3口设置为准双向口
  43.         P4M1 = 0x00;        P4M0 = 0x00;        // P4口设置为准双向口
  44.         P5M1 = 0x00;        P5M0 = 0x00;        // P5口设置为准双向口
  45.         P6M1 = 0x00;        P6M0 = 0x00;        // P6口设置为准双向口
  46.         P7M1 = 0x00;        P7M0 = 0x00;        // P7口设置为准双向口
  47. }
  48. /**
  49. * @brief 主函数,程序入口
  50. */
  51. void main(void)
  52. {
  53.         unsigned char temp; // 定义一个临时变量,用于存储要输出到P2端口的LED状态模式
  54.         Init(); // 调用初始化函数,配置系统和端口
  55.         temp = 0xFE; // 初始化LED模式。0xFE的二进制是 1111 1110。
  56.                  // 假设LED是低电平点亮,那么P20引脚将输出低电平,第一个LED点亮。
  57.         while(1) // 无限循环,让流水灯效果持续进行
  58.         {
  59.         // 使用_crol_函数对temp变量进行循环左移
  60.         // _crol_(temp, 1) 表示将temp的所有位向左移动1位,
  61.         // 最高位移出的位会循环进入最低位。
  62.         // 例如: 1111 1110 -> 1111 1101 -> 1111 1011 ...
  63.                 temp = _crol_(temp, 1);
  64.                 delay_ms(100); // 延时100毫秒,控制流水灯的移动速度
  65.                 P2 = temp; // 将更新后的模式写入P2端口,改变LED的亮灭状态
  66.         }
  67. }
复制代码
IMG_20260102_131706.jpg
IMG_20260102_131707.jpg
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 13:27:52 | 显示全部楼层
学习心得-10  右移流水灯  ,实现成功
  1. /**************************************************************
  2. * 程序功能:STC擎天柱核心板 P2端口 右移流水灯
  3. * 描述:P2端口的8个LED灯从右到左依次循环点亮,形成流水效果。
  4. **************************************************************/
  5. #include <AI8051U.H>      // 包含擎天柱核心板(AI8051U)的寄存器定义头文件
  6. #include <intrins.h>      // 包含C51编译器的内部函数库,例如_cror_循环移位函数
  7. // 定义主时钟频率,用于精确计算延时
  8. #define                MAIN_Fosc        24000000UL  // 定义主时钟频率为24MHz
  9. /**
  10. * @brief 毫秒级延时函数 (软件延时)
  11. * @param ms 需要延时的毫秒数
  12. */
  13. void delay_ms(unsigned char ms)
  14. {
  15.         unsigned int i;
  16.         do
  17.         {
  18.                 i = MAIN_Fosc / 6000;
  19.                 while(--i); // 空循环,通过消耗CPU时间来实现延时
  20.         }
  21.         while(--ms);
  22. }
  23. /**
  24. * @brief 系统初始化函数
  25. */
  26. void Init(void)
  27. {
  28.         WTST = 0;                                        // 设置程序指令等待参数,0为最快速度
  29.         EAXFR = 1;                                        // 使能访问扩展RAM(XFR),操作P4-P7端口的前提
  30.         CKCON = 0;                                        // 设置外部RAM访问时序
  31.         // 将所有GPIO端口设置为准双向口模式
  32.         P0M1 = 0x00;        P0M0 = 0x00;
  33.         P1M1 = 0x00;        P1M0 = 0x00;
  34.         P2M1 = 0x00;        P2M0 = 0x00;
  35.         P3M1 = 0x00;        P3M0 = 0x00;
  36.         P4M1 = 0x00;        P4M0 = 0x00;
  37.         P5M1 = 0x00;        P5M0 = 0x00;
  38.         P6M1 = 0x00;        P6M0 = 0x00;
  39.         P7M1 = 0x00;        P7M0 = 0x00;
  40. }
  41. /**
  42. * @brief 主函数,程序入口
  43. */
  44. void main(void)
  45. {
  46.         unsigned char temp; // 定义一个临时变量,用于存储要输出到P2端口的LED状态模式
  47.         Init(); // 调用初始化函数
  48.     // --- 主要修改点 1: 修改初始值 ---
  49.     // 原来的初始值是 0xFE (二进制 1111 1110),从P20开始亮。
  50.     // 现在我们从P27开始亮,所以初始值应该是 0x7F (二进制 0111 1111)。
  51.         temp = 0x7F;
  52.         while(1) // 无限循环
  53.         {
  54.         // --- 主要修改点 2: 将循环左移改为循环右移 ---
  55.         // _cror_(temp, 1) 表示将temp的所有位向右移动1位,
  56.         // 最低位移出的位会循环进入最高位。
  57.         // 例如: 0111 1111 -> 1011 1111 -> 1101 1111 ...
  58.                 temp = _cror_(temp, 1);
  59.                 delay_ms(100); // 延时100毫秒
  60.                 P2 = temp; // 将更新后的模式写入P2端口
  61.         }
  62. }
复制代码
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:324
  • 最近打卡:2026-02-12 09:05:32

835

主题

1万

回帖

2万

积分

管理员

积分
22170
发表于 2026-1-2 13:51:13 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 17:04:32 | 显示全部楼层
AI8051uU学习心得-11

追逐灯 p2口  看以下程序
  1. #include <AI8051U.H>
  2. #include <intrins.h>
  3. #define                MAIN_Fosc        24000000UL
  4. void delay_ms(unsigned char ms)
  5. {
  6.         unsigned int i;
  7.         do
  8.         {
  9.                 i = MAIN_Fosc / 6000;
  10.                 while(--i);
  11.         }
  12.         while(--ms);
  13. }
  14. void Init(void)
  15. {
  16.         WTST = 0;
  17.         EAXFR = 1;
  18.         CKCON = 0;
  19.         P0M1 = 0x00;        P0M0 = 0x00;
  20.         P1M1 = 0x00;        P1M0 = 0x00;
  21.         P2M1 = 0x00;        P2M0 = 0x00;
  22.         P3M1 = 0x00;        P3M0 = 0x00;
  23.         P4M1 = 0x00;        P4M0 = 0x00;
  24.         P5M1 = 0x00;        P5M0 = 0x00;
  25.         P6M1 = 0x00;        P6M0 = 0x00;
  26.         P7M1 = 0x00;        P7M0 = 0x00;
  27. }
  28. void main(void)
  29. {
  30.         unsigned char temp;
  31.         Init();
  32.     // --- 主要修改点 1: 修改初始值 ---
  33.     // 0x03 的二进制是 0000 0011。
  34.     // 如果LED是低电平点亮,这会使P20和P21同时点亮。
  35.         temp = 0x03;
  36.         while(1)
  37.         {
  38.                 P2 = temp;      // 先将当前模式输出到P2端口
  39.                 delay_ms(100);  // 延时,让眼睛能看清
  40.         // --- 主要修改点 2: 修改移位逻辑 ---
  41.         // 使用_crol_函数将模式整体向左移动一位。
  42.         // 例如: 0000 0011 -> 0000 0110 -> 0000 1100 ...
  43.                 temp = _crol_(temp, 1);
  44.         }
  45. }
复制代码

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 17:12:01 | 显示全部楼层
学习心得-12  简陋版本涟漪灯
  1. #include <AI8051U.H>
  2. #include <intrins.h>
  3. #define                MAIN_Fosc        24000000UL
  4. void delay_ms(unsigned char ms)
  5. {
  6.         unsigned int i;
  7.         do
  8.         {
  9.                 i = MAIN_Fosc / 6000;
  10.                 while(--i);
  11.         }
  12.         while(--ms);
  13. }
  14. void Init(void)
  15. {
  16.         WTST = 0;
  17.         EAXFR = 1;
  18.         CKCON = 0;
  19.         P0M1 = 0x00;        P0M0 = 0x00;
  20.         P1M1 = 0x00;        P1M0 = 0x00;
  21.         P2M1 = 0x00;        P2M0 = 0x00;
  22.         P3M1 = 0x00;        P3M0 = 0x00;
  23.         P4M1 = 0x00;        P4M0 = 0x00;
  24.         P5M1 = 0x00;        P5M0 = 0x00;
  25.         P6M1 = 0x00;        P6M0 = 0x00;
  26.         P7M1 = 0x00;        P7M0 = 0x00;
  27. }
  28. void main(void)
  29. {
  30.         unsigned char i;
  31.         Init();
  32.         while(1)
  33.         {
  34.         // --- 效果一:扩散 (从中间向两边) ---
  35.         // 我们从中间的P23和P24开始亮
  36.         // i=0: 00011000 (0x18) -> P23, P24 亮
  37.         // i=1: 00111100 (0x3C) -> P22, P23, P24, P25 亮
  38.         // i=2: 01111110 (0x7E) -> P21-P26 亮
  39.         // i=3: 11111111 (0xFF) -> P20-P27 亮
  40.                 for(i = 0; i < 4; i++)
  41.                 {
  42.             // 使用位操作来点亮对称的LED
  43.             // (0x08 << i) 负责点亮中间偏左的LED
  44.             // (0x10 << i) 负责点亮中间偏右的LED
  45.             // | (或运算) 将它们合并
  46.                         P2 = ~((0x08 << i) | (0x10 << i));
  47.                         delay_ms(150);
  48.                 }
  49.         // --- 效果二:收缩 (从两边向中间) ---
  50.         // 这个循环与上面的扩散循环正好相反
  51.         // i=3: 11111111 (0xFF) -> P20-P27 亮
  52.         // i=2: 01111110 (0x7E) -> P21-P26 亮
  53.         // i=1: 00111100 (0x3C) -> P22-P25 亮
  54.         // i=0: 00011000 (0x18) -> P23-P24 亮
  55.                 for(i = 3; i > 0; i--)
  56.                 {
  57.                         P2 = ~((0x08 << i) | (0x10 << i));
  58.                         delay_ms(150);
  59.                 }
  60.         // 注意:为了避免在收缩到最小时有一个明显的停顿,
  61.         // 第二个循环的条件是 i > 0。循环结束后,P2的状态是 i=1 时的状态 (0x3C)。
  62.         // 我们可以再加一步,让它收缩到最小点并延时。
  63.         P2 = ~(0x08 | 0x10); // 收缩到最小点 (0x18)
  64.         delay_ms(150);
  65.         }
  66. }
复制代码


代码注释中有关键代码注释,有意思。
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 17:18:04 | 显示全部楼层
学习心得-13  对冲-绽放灯


  1. #include <AI8051U.H>      // 包含擎天柱核心板寄存器定义头文件
  2. #include <intrins.h>      // 包含内部函数库 (虽然本程序没用,但通常会包含)
  3. #define                MAIN_Fosc        24000000UL  // 定义主时钟频率为24MHz
  4. /**
  5. * @brief 毫秒级延时函数 (软件延时)
  6. * @param ms 需要延时的毫秒数
  7. */
  8. void delay_ms(unsigned char ms)
  9. {
  10.         unsigned int i;
  11.         do
  12.         {
  13.                 i = MAIN_Fosc / 6000;
  14.                 while(--i);
  15.         }
  16.         while(--ms);
  17. }
  18. /**
  19. * @brief 系统初始化函数
  20. */
  21. void Init(void)
  22. {
  23.         WTST = 0;                                        // 设置程序指令等待参数,0为最快速度
  24.         EAXFR = 1;                                        // 使能访问扩展RAM(XFR)
  25.         CKCON = 0;                                        // 设置外部RAM访问时序
  26.         // 将所有GPIO端口设置为准双向口模式
  27.         P0M1 = 0x00;        P0M0 = 0x00;
  28.         P1M1 = 0x00;        P1M0 = 0x00;
  29.         P2M1 = 0x00;        P2M0 = 0x00;
  30.         P3M1 = 0x00;        P3M0 = 0x00;
  31.         P4M1 = 0x00;        P4M0 = 0x00;
  32.         P5M1 = 0x00;        P5M0 = 0x00;
  33.         P6M1 = 0x00;        P6M0 = 0x00;
  34.         P7M1 = 0x00;        P7M0 = 0x00;
  35. }
  36. /**
  37. * @brief 主函数,程序入口
  38. */
  39. void main(void)
  40. {
  41.         unsigned char i;
  42.     unsigned char pattern; // 用于存储LED亮灭模式的变量
  43.         Init(); // 调用初始化函数
  44.         while(1) // 无限循环,让效果持续进行
  45.         {
  46.         // --- 效果一:收缩 (从两端向中间点亮) ---
  47.         pattern = 0x00; // 初始模式为全灭
  48.                 for(i = 0; i < 4; i++)
  49.                 {
  50.             // 核心逻辑:使用位操作来点亮对称的LED
  51.             // (0x01 << i)       : 点亮从左边数第i个LED (P20, P21, P22, P23)
  52.             // (0x80 >> i)       : 点亮从右边数第i个LED (P27, P26, P25, P24)
  53.             // pattern |= ...    : 将新点亮的LED状态合并到当前模式中
  54.             pattern |= (0x01 << i) | (0x80 >> i);
  55.             P2 = ~pattern; // 将模式输出到P2端口 (低电平点亮,所以需要取反)
  56.                         delay_ms(200); // 延时,控制动画速度
  57.                 }
  58.         // --- 效果二:绽放 (从中间向两端点亮) ---
  59.         // 这个循环与上面的收缩循环正好相反
  60.                 for(i = 3; i > 0; i--)
  61.                 {
  62.             // 核心逻辑:使用位操作来熄灭对称的LED
  63.             // ~((0x01 << i) | (0x80 >> i)) : 创建一个掩码,将要熄灭的LED位置设为0
  64.             // pattern &= ...              : 使用与运算,将pattern中对应的位清零
  65.             pattern &= ~((0x01 << i) | (0x80 >> i));
  66.             
  67.             P2 = ~pattern; // 将更新后的模式输出到P2端口
  68.                         delay_ms(200); // 延时
  69.                 }
  70.         // 为了让动画更流畅,在绽放结束后,可以再灭一次最中间的灯
  71.         pattern = 0x00;
  72.         P2 = ~pattern;
  73.         delay_ms(200);
  74.         }
  75. }
复制代码
IMG_20260102_171704.jpg
IMG_20260102_171705.jpg
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2026-02-12 08:01:00
已绑定手机

1

主题

33

回帖

399

积分

中级会员

积分
399
发表于 2026-1-2 17:31:06 | 显示全部楼层
学习心得-14  数码管显示“8”,共阳极

  1. #include <AI8051U.H>      // 包含擎天柱核心板寄存器定义头文件
  2. /**
  3. * @brief 系统初始化函数
  4. */
  5. void Init(void)
  6. {
  7.         WTST = 0;                                        // 设置程序指令等待参数,0为最快速度
  8.         EAXFR = 1;                                        // 使能访问扩展RAM(XFR)
  9.         CKCON = 0;                                        // 设置外部RAM访问时序
  10.         // 将P2端口设置为准双向口模式
  11.         P2M1 = 0x00;
  12.         P2M0 = 0x00;
  13. }
  14. /**
  15. * @brief 主函数,程序入口
  16. */
  17. void main(void)
  18. {
  19.         Init(); // 调用初始化函数
  20.     // --- 核心代码 ---
  21.     // 将P2端口赋值为0x80,以在共阳数码管上显示数字“8”
  22.     // 0x80 的二进制是 1000 0000
  23.     // 这会使 P20-P26 输出低电平 (点亮a-g段), P27输出高电平 (熄灭dp段)
  24.         P2 = 0x80;
  25.         while(1)
  26.         {
  27.         // 程序卡在死循环中,数码管将一直显示“8”
  28.         }
  29. }
复制代码
IMG_20260102_172901.jpg
IMG_20260102_172905.jpg
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-2-12 18:02 , Processed in 0.132496 second(s), 80 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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