找回密码
 立即注册
楼主: 乐高

AI8051U教学视频课后小练 | 高质量打卡

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2025-05-03 13:57:08
已绑定手机

1

主题

60

回帖

287

积分

中级会员

积分
287
发表于 2025-1-28 21:01:11 | 显示全部楼层
第十五集 定时器做计数器

15集 CT计数器.png
  1. void INT1_Count_Init(void)
  2. {
  3.         IT1 =1;
  4.   EX1 = 1;       
  5. }
  6. void INT1_Isr() interrupt 2
  7. {
  8.         Count1 = Count_T1;
  9.         if(Count1>5)
  10.         {
  11.                 Count = Count1/10;
  12.           Count_INT1++;
  13.         }       
  14.          Count_T1 = 0;       
  15. }       
  16. void Timer1_Isr(void) interrupt 3
  17. {
  18.         Count_T1++;
  19. }
  20. void Timer1_Init(void)                //10毫秒@24.000MHz
  21. {
  22.         AUXR &= 0xBF;                        //定时器时钟12T模式
  23.         TMOD &= 0x0F;                        //设置定时器模式
  24.         TL1 = 0xE0;                                //设置定时初始值
  25.         TH1 = 0xB1;                                //设置定时初始值
  26.         TF1 = 0;                                  //清除TF1标志
  27.         TR1 = 1;                                  //定时器1开始计时
  28.         ET1 = 1;                                  //使能定时器1中断
  29. }
复制代码
15 定时器做计shu器.zip (170.52 KB, 下载次数: 20)
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2025-05-03 13:57:08
已绑定手机

1

主题

60

回帖

287

积分

中级会员

积分
287
发表于 2025-1-30 13:22:15 | 显示全部楼层
第十六集 DS18B20测温  课后小任务
把温度传感器的数值显示改成两位数,加一小数点,然后小数点后再显示一位。
18B20 课后小任务.png
先在程序中加入转换精度可预设的代码:
  1. void DS18B20_Init(void)
  2. {
  3.                         DS18B20_Reset();                    //1.发送复位命令
  4.                         DS18B20_WriteByte(0xcc);        //2.跳过ROM命令
  5.                         DS18B20_WriteByte(0x4e);       //3.写暂存器指令4E
  6.                         DS18B20_WriteByte(0x4b);        //4.写TH最高限值温度
  7.                         DS18B20_WriteByte(0x00);        //5.写TL最低限值温度
  8.                         DS18B20_WriteByte(0x7f);        //写配置寄存器4
  9.                                                 //0x1f : 0.5000°C  转换时间93.75ms
  10.                                                 //0x3f : 0.2500°C  转换时间187.5ms
  11.                                                 //0x5f : 0.1250°C  转换时间375ms
  12.                                                 //0x7f : 0.0625°C  转换时间750ms
  13. }
复制代码
       Temp_18b20 = Temp_18b20/1000;        //除1000,再在十位数之后加上小数点,则显示出需要的数值。
  1. u8 SEG_NUM1[]=                                //带小数点
  2. {
  3.     0xBF,       /*'0', 0*/
  4.     0x86,       /*'1', 1*/
  5.     0xDB,       /*'2', 2*/
  6.     0xCF,       /*'3', 3*/
  7.     0xE6,       /*'4', 4*/
  8.     0xED,       /*'5', 5*/
  9.     0xFD,       /*'6', 6*/
  10.     0x87,       /*'7', 7*/
  11.     0xFF,       /*'8', 8*/
  12.     0xEF,       /*'9', 9*/
  13.     0xF7,       /*'A', 10*/
  14.     0xFC,       /*'B', 11*/
  15.     0xB9,       /*'C', 12*/
  16.     0xDE,       /*'D', 13*/
  17.     0xF9,       /*'E', 14*/
  18.     0xF1,       /*'F', 15*/
  19.     0x40,       /*'-', 16*/
  20.     0x00,       /*' ', 17*/
  21.     0x80,       /*'.', 18*/
  22. };
复制代码
只显示三位数字
  1. void SEG_Show_U32(u32 num)
  2. {
  3.         u8 i;
  4.         for(i=0;i<3;i++)                      //只显示三位数字
  5.         {
  6.                 passward[7-i] = num%10;
  7.                 num /= 10;
  8.         }
  9. }
复制代码
demo1.zip (195.65 KB, 下载次数: 41)



IMG_20250130_132443.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2025-05-03 13:57:08
已绑定手机

1

主题

60

回帖

287

积分

中级会员

积分
287
发表于 2025-1-30 18:34:54 | 显示全部楼层
第十六集 DS18B20测温  课后小练

第十六集 18B20测温.png
鉴于实验箱没有真正的电源开关机按键,所以采用右侧的某个键盘象征性的作为开关机键使用,但不能真正切断电源。
由于四个独立按键P32\P33\P34\P35都已经被占用,所以考虑用矩阵键盘来实现此课后小练的功能。
此处采用按键1(P01)作为开关机键,按键3(P03)作为摄氏华氏温度显示方式切换键。
下面是main主函数

  1. while(1)
  2.         {
  3. //               
  4. //    if (bUsbOutReady)                                                                                                        //如果接收到了数据
  5. //        {
  6. //            //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
  7. //                       
  8. //            usb_OUT_done();                                                        //
  9. //        }
  10.                 Task_Pro_Handler_Callback();                                //执行功能函数
  11.                 if(C_F == 0)
  12.                                 SEG_Show_U32(Temp_18b20);                                //如果C_F=0,则显示摄氏温度
  13.                 else
  14.                           SEG_Show_U32(Temp_F);                                                //如果C_F=1,则显示华氏温度
  15.    if(P01==0)                                                                                                                //按键1用作开关机键
  16.          {
  17.                         Delay20ms();
  18.                   if(P01==0)
  19.                         {
  20.                                 run = !run;
  21.                                 Key_num=0;
  22.                         }
  23.                         while(P01==0);
  24.          }
  25.         }
  26. }
复制代码
  1. void Key_Task(void)        
  2. {        
  3.         Key_num++;
  4.         if(P03==0)                                                                                //按键3用作摄氏/华氏显示切换键
  5.                 {        
  6.                         Key_Vol++;
  7.                         Key_num = 0;
  8.                         if(Key_Vol==5)               
  9.                         {
  10.                                 C_F = !C_F;
  11.                         }
  12.                 }
  13.         else
  14.                 Key_Vol = 0;
  15.         if(Key_num==3000)                                                 //30秒无操作,关机
  16.                 run = 0;
  17. }
复制代码
  1. void SEG_Task(void)
  2. {
  3.         u8 num = 0;
  4.         
  5.         if(run==0)                       //未按P01键,熄屏,代表未开机
  6.         {
  7.                         tim =0;
  8.       SEG_Show0();                                                                 //未开机,熄屏
  9.   }
  10.         else
  11.         {
  12.                 tim++;
  13.                 if(tim>2000)                                                  //2秒钟后
  14.                 {
  15.                         if(C_F)
  16.                                 SEG_Show4();                                                        //如果C_F=1,则显示华氏温度
  17.                         else
  18.                                 SEG_Show3();                                                        //如果C_F=0,则显示摄氏温度
  19.                         tim = 2000;
  20.    }
  21.                 else                                                                                                        //2秒内
  22.                 {
  23.                         if(C_F)
  24.                                 SEG_Show2();                                                        //如果C_F=1,显示”---F"
  25.                         else
  26.                                 SEG_Show1();                                                        //如果C_F=0,显示”---C“
  27.           }                        
  28.         }
  29.         Seg_no ++;
  30.         if( Seg_no>7 )
  31.                 Seg_no=0;
  32. }
复制代码

demo2.zip (204.35 KB, 下载次数: 29)


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2025-05-03 13:57:08
已绑定手机

1

主题

60

回帖

287

积分

中级会员

积分
287
发表于 2025-1-31 19:06:21 | 显示全部楼层
第十六集 DS18B20测温  数码管闪烁问题

18B20阻塞程序导致数码管显示闪烁.png
数码管闪烁是由于18B20的读写中采用了阻塞延时程序(软件延时)影响了主程序的运行,要采用非阻塞程序才能使数码管不闪烁。
非阻塞写法有多种,我现在找到了一种:定时器中断方式。用定时器中断来实现精确延时。
本程序中使用定时器1,设置定时长度为60us, 480us就是8个定时周期,420us正好是7个定时周期。
18B20全部的读写过程都在定时中断中实现
  1. void Timer1_Isr(void) interrupt 3         //定时时间60us,就是60us走一步
  2. {
  3.         switch(t1_num)
  4.                 {
  5.                 case 0 :
  6.                 case 33 :
  7.                 bz = 1; DQ = 0; break;
  8.                 case 8 :                                                                                                                        //0-8步时间间隔480us
  9.                 case 41 :
  10.                 DQ = 1; break;
  11.                 case 9 :                                                                                                                        //8-9步时间间隔60us
  12.                 case 42 :
  13.                 bz = DQ; break;
  14.                 case 16 :                            //9-16步时间间隔420us
  15.                 case 49 :
  16.                 if(bz)                                                                                                                         //如果bz为1,则初始化失败,关闭定时器1,等待下次采集。
  17.                 {
  18.                         TR1 = 0;
  19.                         break;}
  20.                 else                                                                                                                                 //如果bz为0,则开始写入命令cmd[cmd_n++]
  21.                 {
  22.                   dat = cmd[cmd_n++];
  23.                         DQ = 0;
  24.                         Delay1us();
  25.                   dat >>= 1;
  26.                         DQ = CY;
  27.                         break;
  28.                 }
  29.                 case 17 : //cmd[0]
  30.                 case 18 :
  31.                 case 19 :
  32.                 case 20 :
  33.                 case 21 :
  34.                 case 22 :
  35.                 case 23 :
  36.                 case 25 : //cmd[1]
  37.                 case 26 :
  38.                 case 27 :
  39.                 case 28 :
  40.                 case 29 :
  41.                 case 30 :
  42.                 case 31 :
  43.                 case 50 : //cmd[2]
  44.                 case 51 :
  45.                 case 52 :
  46.                 case 53 :
  47.                 case 54 :
  48.                 case 55 :
  49.                 case 56 :
  50.                 case 58 : //cmd[3]
  51.                 case 59 :
  52.                 case 60 :
  53.                 case 61 :
  54.                 case 62 :
  55.                 case 63 :
  56.                 case 64 :
  57.                  DQ = 1;
  58.                  Delay1us();  
  59.                  DQ = 0;
  60.                  Delay1us();                                          //开始下一位
  61.                  dat >>= 1;
  62.                  DQ = CY;
  63.                 break;
  64.                 case 24 :
  65.                 case 57 :
  66.                 DQ = 1;
  67.                 Delay1us();                                           //写第一个字节结束
  68.                 dat = cmd[cmd_n++];      
  69.                 DQ = 0;
  70.                 Delay1us();                                           //写第二个字节
  71.                 dat >>= 1;
  72.                 DQ = CY;
  73.                 break;
  74.                 case 32 :
  75.                 DQ = 1;
  76.                 Delay1us();                                           //写第二个字节结束 0x44
  77.                 case 65 :
  78.                 DQ = 1;
  79.                 Delay1us();                                    //0xbe 命令发完
  80.                 dat = 0;                        
  81.                 dat >>= 1;
  82.                 DQ = 0;
  83.                 Delay1us();  
  84.                 DQ = 1;
  85.                 Delay1us();  
  86.                 if(DQ) dat |= 0x80;
  87.                 break;
  88.                 case 66 :
  89.                 case 67 :
  90.                 case 68 :
  91.                 case 69 :
  92.                 case 70 :
  93.                 case 71 :
  94.                 case 72 :
  95.                 case 74 :
  96.                 case 75 :
  97.                 case 76 :
  98.                 case 77 :
  99.                 case 78 :
  100.                 case 79 :
  101.                 case 80 :
  102.                 dat >>= 1;
  103.                 DQ = 0;
  104.                 Delay1us();  
  105.                 DQ = 1;
  106.                 Delay1us();  
  107.                 if(DQ) dat |= 0x80;
  108.                 break;
  109.                 case 73 :
  110.                 TempL = dat;
  111.                 dat = 0;         
  112.                 dat >>= 1;
  113.                 DQ = 0;
  114.                 Delay1us();
  115.                 DQ = 1;
  116.                 Delay1us();
  117.                 if(DQ) dat |= 0x80;
  118.                 break;
  119.                 case 81 :
  120.                 TempH = dat;
  121.                 TR1 = 0;
  122.                 break;
  123.                 default : break;
  124.                 }        
  125.         t1_num++;
  126. }
复制代码
  1. void Timer1_Init(void)                //60微秒@24.000MHz
  2. {
  3.         AUXR &= 0xBF;                        //定时器时钟12T模式
  4.         TMOD &= 0x0F;                        //设置定时器模式
  5.         TL1 = 0x88;                                //设置定时初始值
  6.         TH1 = 0xFF;                                //设置定时初始值
  7.         TF1 = 0;                                //清除TF1标志
  8.         TR1 = 1;                                //定时器1开始计时
  9.         ET1 = 1;                                //使能定时器1中断
  10. }
复制代码
温度值计算放在main函数内,因为怕60us时间不够用。
  1. while(1)
  2.         {
  3. //               
  4. //    if (bUsbOutReady)                                                                                                        //如果接收到了数据
  5. //        {
  6. //            //USB_SendData(UsbOutBuffer,OutNumber);   //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
  7. //                        
  8. //            usb_OUT_done();                                                        //
  9. //        }
  10.                 Task_Pro_Handler_Callback();                                //执行功能函数
  11.         if( TempH & 0x80 )                        //如果最高位是1,这个就是负数
  12.         {
  13.                 MinusFlag = 1;
  14.                 Temp = (((u16)TempH << 8) | ((u16)TempL << 0));
  15.                 Temp = (~Temp) +1;
  16.                 Temp_18b20 = (u32)Temp*625;
  17.         }
  18.         else
  19.         {
  20.                 MinusFlag = 0;
  21.                 Temp = (((u16)TempH << 8) | ((u16)TempL << 0));
  22.                 Temp_18b20 = (u32)Temp*625;
  23.                 Temp_18b20 = Temp_18b20/1000;        //除1000,再在十位数之后加上小数点,则显示出需要的数值。
  24.                 Temp_F = Temp_18b20*9/5 + 320;                         //转换成华氏温度值
  25.         }        
  26.                 if(C_F == 0)
  27.                                 SEG_Show_U32(Temp_18b20);                                //如果C_F=0,则显示摄氏温度
  28.                 else
  29.                           SEG_Show_U32(Temp_F);                                                //如果C_F=1,则显示华氏温度
  30.    if(P01==0)                                                                                                                //按键1用作开机键
  31.          {
  32.                         Delay20ms();
  33.                   if(P01==0)
  34.                         {
  35.                                 run = !run;
  36.                                 Key_num=0;
  37.                         }
  38.                         while(P01==0);
  39.          }
  40.         }
  41. }
复制代码
  1. u8 t1_num = 0;
  2. u8 cmd_n = 0;
  3. void Key_Task(void)       
  4. {       
  5.         Key_num++;
  6.                 if(Key_num%50==0)           //本处设置温度采集周期,500ms采集一次温度
  7.                 {
  8.                         //num = 0;
  9.                         t1_num = 0; cmd_n = 0; //nodevice = 0;
  10.                         TR1 = 1;
  11.                 }
  12.         if(P03==0)                                                                                //按键3用作摄氏/华氏显示切换键
  13.                 {       
  14.                         Key_Vol++;
  15.                         Key_num = 0;
  16.                         if(Key_Vol==5)               
  17.                         {
  18.                                 C_F = !C_F;
  19.                         }
  20.                 }
  21.         else
  22.                 Key_Vol = 0;
  23.         if(Key_num==3000)                                                 //30秒无操作,关机
  24.                 run = 0;
  25. }
复制代码

其他的程序跟前面课后小练中的一样,DS18B20_ReadTemp函数不用了。

demo3.zip (206.82 KB, 下载次数: 26)
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:85
  • 最近打卡:2025-03-06 07:45:38

7

主题

49

回帖

534

积分

高级会员

积分
534
发表于 2025-2-1 16:00:49 | 显示全部楼层

楼主没考虑用掉电模式PD=1来实现关机吗?

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2025-05-03 13:57:08
已绑定手机

1

主题

60

回帖

287

积分

中级会员

积分
287
发表于 2025-2-2 13:56:19 | 显示全部楼层
silas*** 发表于 2025-2-1 16:00
楼主没考虑用掉电模式PD=1来实现关机吗?

谢谢同学的提醒,我还没有用过MCU的掉电功能呢,这次尝试一下。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:111
  • 最近打卡:2025-05-03 13:57:08
已绑定手机

1

主题

60

回帖

287

积分

中级会员

积分
287
发表于 2025-2-2 15:06:29 | 显示全部楼层
第十六集 DS18B20测温    掉电及掉电唤醒
主程序main函数while(1)循环前加入掉电及掉电唤醒功能
  1. P0IM0 = 0x00;                                    //下降沿中断
  2.         P0IM1 = 0x00;
  3. //PINIPH=0x01;                  //设置P0口GPIO中断为最高优先级
  4. //PINIPL=0x01;
  5.         P0INTE = 0x02;                                                                //使能P01中断功能
  6.         P0WKUE = 0x02;                                                                //使能P01中断掉电唤醒功能
  7.   EA = 1;                                                                                                //IE |= 0X80;        
  8.   while (DeviceState != DEVSTATE_CONFIGURED);     //等待USB完成配置
  9. //P40 = 0;
  10.         P06 = 0;                      //给P01,P03提供低电平
  11.         _nop_();
  12.         _nop_();
  13.         
  14.         PD = 1 ;                                                                                        //MCU进入掉电模式        ,        PCON = 0x02;                                
  15.         _nop_();                      //掉电模式被唤醒后,MCU首先会执行此语句
  16.         _nop_();                      //然后再进入中断服务程序
  17.         _nop_();
  18.         _nop_();
  19.    
  20.         while(1)
复制代码
  1. void common_irs() interrupt 37                                        //使用GPIO,P01口中断
  2. {
  3.         u8 intf;                        
  4.         intf = P0INTF;
  5.         P0INTF = 0x00;                                                                 //清空中断标志位,以正常保证中断请求
  6.         if(intf & 0x02)                             
  7.         {
  8.                 run = !run;
  9.         }
  10. }
复制代码
  1. void SEG_Task(void)
  2. {        
  3.         if(run==0)                       //未按P01键,熄屏,代表未开机
  4.         {
  5.                         tim =0;
  6.       SEG_Show0();                                                                 //未开机,熄屏
  7.                         PD = 1;                                                                                         //熄屏以后再掉电,不然数码管还有残余显示
  8.                         Key_num = 0;
  9.   }
  10.         else
  11.         {
  12.                 PD = 0;                       
  13.                 tim++;
  14.                 if(tim>2000)                                                  //2秒钟后
  15.                 {
  16.                         if(C_F)
  17.                                 SEG_Show4();                                                        //如果C_F=1,则显示华氏温度
  18.                         else
  19.                                 SEG_Show3();                                                        //如果C_F=0,则显示摄氏温度
  20.                         tim = 2000;
  21.    }
  22.                 else                                                                                                        //2秒内
  23.                 {
  24.                         if(C_F)
  25.                                 SEG_Show2();                                                        //如果C_F=1,显示”---F"
  26.                         else
  27.                                 SEG_Show1();                                                        //如果C_F=0,显示”---C“
  28.           }                        
  29.         }
  30.         Seg_no ++;
  31.         if( Seg_no>7 )
  32.                 Seg_no=0;
  33. }
复制代码
demo4.zip (207.77 KB, 下载次数: 38)


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:85
  • 最近打卡:2025-03-06 07:45:38

7

主题

49

回帖

534

积分

高级会员

积分
534
发表于 2025-2-4 12:38:56 | 显示全部楼层

https://www.stcaimcu.com/forum.php?mod=viewthread&tid=12763&extra=&page=4

感谢提供的思路,我也完成作业了

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2025-05-03 11:09:27
已绑定手机

83

主题

291

回帖

409

积分

中级会员

积分
409
发表于 2025-2-26 09:37:18 | 显示全部楼层
感谢分享,期待15、16集作业后续。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2025-05-03 11:09:27
已绑定手机

83

主题

291

回帖

409

积分

中级会员

积分
409
发表于 2025-2-26 09:37:26 | 显示全部楼层
感谢分享,期待15、16集作业后续。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-3 15:02 , Processed in 1.129273 second(s), 111 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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