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

认真学《32位8051单片机原理及C语言程序设计视频教程》 【免费+包邮送】32G12K128-实

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-19 13:51:25 | 显示全部楼层
xiaoxi*** 发表于 2025-2-19 13:48
第十四集讲的是矩阵按键,跟AI8051U中的矩阵按键 讲的是一样的。刚开始看到这个图的时候,我好一会没有明白 ...

这个R59和R60,这两个电阻在矩阵按键当中是没有用处的。不过它不影响什么。课里面没有讲到,好一会我一直在想,它们是做什么用处的,后来才想明白原来是没有用处啊!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-19 17:02:15 | 显示全部楼层
第十五集外部中断,本节课讲 了外部中断一共有五个,其中0各1具有边缘中断和下降沿中断,2 3 4 只有下降沿中断,还讲到了引脚是固定的,不能切换引脚 。值得注意的是,定时器零可设为不可被 打断的中断,这里讲优先级的时候,可以讲一下这个。只要这个中断正在执行,不会被其它任何中断再打断。不能被 中断嵌套。不过有一点不明白,为什么中断函数还需要在主函数里面?为什么不写在exrt.c里面呢?中断初始化函数和中断函数都应该在这里面啊。这明明是属于中断部分啊。
void INT0_Isr(void) interrupt 0
{
//        SEG0 += 1;                                    
}

void P3Exit_Isr(void) interrupt 40
{
        u8 intf;
        intf = P3INTF;                              
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-20 20:21:12 | 显示全部楼层
AUXR = 0x80;    //Timer0 set as 1T, 16 bits timer auto-reload,
    TH0 = (u8)(Timer0_Reload / 256);
    TL0 = (u8)(Timer0_Reload % 256);
    ET0 = 1;   
    TR0 = 1;   
    EA = 1;   
   
    for(i=0; i<8; i++)  LED8[i] = 0x10;

今天看了官方的NTC测温的事例代码。在定是器0的自动重装载模式下,重载值的写法可以有三种:

1.   TH0 = (u8)(Timer0_Reload / 256);
      TL0 = (u8)(Timer0_Reload % 256);

(u8)(Timer0_Reload / 256):
Timer0_Reload / 256 进行的是整数除法运算。在二进制里,除以 256相当于把这个 16 位的数右移 8 位,得到的结果就是这个 16 位数值的高 8 位。
(u8) 是强制类型转换,把结果转换为 8 位无符号整数,然后赋值给 TH0 寄存器。
(u8)(Timer0_Reload % 256):
Timer0_Reload % 256 进行的是取模运算。取模 256 可以得到这个 16 位数值的低 8 位。
同样通过 (u8) 强制类型转换为 8 位无符号整数,再赋值给 TL0 寄存器。


2.   TH0 = (u8)(Timer0_Reload>>8);
      L0 = (u8)(Timer0_Reload );

(u8)(Timer0_Reload>>8):
Timer0_Reload>>8 是位运算,将 Timer0_Reload 这个 16 位的数右移 8 位,这样就把高 8 位移动到了低 8 位的位置。
然后通过 (u8) 强制类型转换为 8 位无符号整数,赋值给 TH0 寄存器。
(u8)(Timer0_Reload ):
直接把 Timer0_Reload 进行 (u8) 强制类型转换,由于 (u8) 是 8 位无符号整数类型,所以会截取 Timer0_Reload 的低 8 位,赋值给 TL0 寄存器。


两者有如下的不同之处。

运算效率:
位运算(第二组代码)的执行速度通常比除法和取模运算(第一组代码)要快。因为除法和取模运算在硬件实现上相对复杂,需要更多的时钟周期;而位运算直接对二进制位进行操作,硬件实现简单,速度快。
代码可读性:
第一组代码使用除法和取模运算,从数学角度更容易理解,对于不熟悉位运算的开发者来说,可能更直观。
第二组代码使用位运算,对于熟悉二进制和位操作的开发者来说,能更清晰地看出是在进行高低 8 位的拆分,代码更简洁。

3.  TH0 = (u8)(Timer0_Reload>>8);
     TL0 = (u8)(Timer0_Reload & 0xFF);   

第二组代码中 TL0 = (u8)(Timer0_Reload ); 会导致 Timer0_Reload 的高 8 位丢失,但只要在程序上没有修改过Timer0_Reload的值 ,就不需要要写第三种。
   
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-20 20:42:37 | 显示全部楼层
xiaoxi*** 发表于 2025-2-20 20:21
AUXR = 0x80;    //Timer0 set as 1T, 16 bits timer auto-reload,
    TH0 = (u8)(Timer0_Reload / 256) ...

因为寄存器是个影子寄存器,重新装入的时候,会存入影子值,它因为失去了与Timer0_Reload的关系,所以如果修改了Timer0_Reload的值,TL0不会更新,所以会出错。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-20 21:00:58 | 显示全部楼层
第十三集第二小节中讲写P6会乱码,其实应该不会,因为  #define        SEG_SEG  P6  所以编译器在编译的时候会把SEG_SEG全部替换会P6啊,因为是分时啊。又不在同一个时间,怎么会乱码呢?变量只是相当于两个不同的事物,然后起了两个不同的名称,根乱不乱码没有关系!不过这样看起来容易区分,思路清晰一些。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-20 21:31:38 | 显示全部楼层
第十三集第三小节u16 Count[8] = {0,0,0,0,0,0,0,0};这里定义了8个成员的数组,还可以写为u16 Count[8] = {};和u16 Count[] = {0,0,0,0,0,0,0,0};因为声明了有8个成员,所以就不需要列出了,后面既然列出了8个成员,所以也就不需要声明8个了。冲哥很细心,即列出成员,又声明了成员个数,这样让我们这些学生能更好的理解。

for(i=0;i<8;i++)                                       
        {
                if( ~KEY & ( 1<<i ) )                //可是这里与个1干嘛呀?与跟不与没有区别,不与1它也能进,而且它也只能是这个位。       
                {
                        if( Count[i]<60000 )
20250220212537.png
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-20 22:30:56 | 显示全部楼层
xiaoxi*** 发表于 2025-2-20 21:31
第十三集第三小节u16 Count[8] = {0,0,0,0,0,0,0,0};这里定义了8个成员的数组,还可以写为u16 Count[8] = { ...

噢,搞错了。if( ~KEY ) 这一判断条件存在问题。此条件只是单纯检查 KEY(通常代表 P3 端口)是否有按键按下,并未具体针对当前循环中所对应的第 i 个按键进行判断。这就会造成无论当前循环到哪个按键,都会以整个 P3 端口是否有按键按下作为判断依据,从而无法准确区分每个按键的状态。 这个按键好难!看了5遍了,还是理解不了,特别是后面那个判断部分。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-21 16:56:52 | 显示全部楼层
for(i=0;i<8;i++)                                       
        {
                if( ~KEY & ( 1<<i ) )                //if ((KEY & (1 << i)) == 0)      这里这样写更直观一些
                {
                        if( Count<60000 )

if (KEY == ~(1 << i))
  • 该条件判断 KEY 是否完全等于 ~(1 << i)。也就是说,KEY 的所有位都必须与 ~(1 << i) 的对应位相同,条件才会成立。例如,当 i = 2 时,只有当 KEY 为二进制 1111 1011 时,条件才为真。
  • 适用于需要精确匹配某个特定二进制模式的场景,即要求 KEY 的所有位都符合 ~(1 << i) 的值。
  • 只能按下一个按键并且是i位对应的这一个,才能进入IF语句。

if ((KEY & (1 << i)) == 0)    与 if( ~KEY & ( 1<<i ) )  
  • 该条件判断 KEY 和 1 << i 按位与的结果是否为 0。这意味着只要 KEY 在第 i 位上是 0,条件就会成立,而 KEY 的其他位可以是任意值。例如,当 i = 2 时,只要 KEY 的第 2 位是 0,无论其他位是什么,条件都为真。
  • 常用于检查 KEY 的某一位是否为 0,而不关心其他位的值,例如在读取硬件寄存器的某一位状态时经常使用。
  • 可以同时按上多个按键,但是只有i位对应的这一个会被加一。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-21 21:13:12 | 显示全部楼层

if ((KEY & (1 << i)) == 0)    与 if( ~KEY & ( 1<<i ) )   其实在这节课里这两个表达方法起到的作用都是一样的,因为是轮询的方式加一,所以每次i等于多少,每次就只能在这一个位的值上加一。一个FOR循环下来,每个按下的位都加了一,也可以看作是同时加了一。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:137
  • 最近打卡:2025-05-01 00:01:04

6

主题

277

回帖

1110

积分

金牌会员

积分
1110
发表于 2025-2-21 21:43:06 | 显示全部楼层
xiaoxi*** 发表于 2025-2-20 21:31
第十三集第三小节u16 Count[8] = {0,0,0,0,0,0,0,0};这里定义了8个成员的数组,还可以写为u16 Count[8] = { ...

u16 Count[8];定义的是全局变量,这样写就可以了。它们8个成员的初值都会默认为0
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-3 08:12 , Processed in 0.131661 second(s), 102 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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