数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 3408|回复: 9

[C51] 请教一段代码的涵义

[复制链接]
发表于 2020-10-15 21:27:18 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
以下是STC-ISP软件中自带的一段实现PCA捕获功能的程序,但这一块实在是没见过,请教大家
  1. void PCA_Isr() interrupt 7
  2. {
  3.     if (CF)
  4.     {
  5.         CF = 0;
  6.         cnt++;                                  //PCA计时溢出次数+1
  7.     }
  8.     if (CCF0)
  9.     {
  10.         CCF0 = 0;
  11.         count0 = count1;                        //备份上一次的捕获值
  12.         ((unsigned char *)&count1)[3] = CCAP0L;         //<font color="#ff0000" size="6">这里开始的四行是什么意思?</font>
  13.         ((unsigned char *)&count1)[2] = CCAP0H;
  14.         ((unsigned char *)&count1)[1] = cnt;
  15.         ((unsigned char *)&count1)[0] = 0;
  16.         length = count1 - count0;              //length保存的即为捕获的脉冲宽度
  17.     }
  18. }
复制代码


 楼主| 发表于 2020-10-15 21:27:57 | 显示全部楼层
((unsigned char *)&count1)[3] = CCAP0L;
这里的四行,请教
回复 支持 反对

使用道具 举报

发表于 2020-10-15 21:41:46 | 显示全部楼层
count1)[  ]是数组
回复 支持 反对

使用道具 举报

发表于 2020-10-15 22:26:36 | 显示全部楼层
我猜CCAP0L; CCAP0H是16位变量存八位数组里,所以分高低8位,cnt是给CF计数的。
回复 支持 反对

使用道具 举报

发表于 2020-10-16 08:41:41 | 显示全部楼层
楼主应该看全一点的代码,,前面定义部分
unsigned long count1;                           //记录本次的捕获值

sfr CCAP0L      =   0xEA;           //PCA模块0捕获寄存器 LOW
sfr CCAP0H      =   0xFA;           //PCA模块0捕获寄存器 HIGH



所以,
        ((unsigned char *)&count1)[3] = CCAP0L;         /
        ((unsigned char *)&count1)[2] = CCAP0H;
        ((unsigned char *)&count1)[1] = cnt;
        ((unsigned char *)&count1)[0] = 0;
是访问 count1 地址,然后逐个 byte 赋值

回复 支持 反对

使用道具 举报

发表于 2020-10-16 18:31:18 | 显示全部楼层
count1是一个32位的变量,
CCAP0是16位的变量,
cnt应该是CCAP0每溢出一次加1,

这4句是把一个16位变量和一个8位变量组成一个32位变量 ,以扩大计数范围。
类似,count1是4位数,,
其中个位是CCAP0L,
十位是CCAP0H,
百位是cnt,
千位是0.
不过这里是十六进制的。而不是十进制的。

只用CCAP0计数范围是0~0xFFFF,再加上cnt做高位,计数范围可以达到0~0xFFFFFF。
回复 支持 反对

使用道具 举报

发表于 2020-10-17 01:31:30 | 显示全部楼层
本帖最后由 lyy-cy 于 2020-10-17 01:40 编辑
mousebat04 发表于 2020-10-16 18:31
count1是一个32位的变量,
CCAP0是16位的变量,
cnt应该是CCAP0每溢出一次加1,

楼上正解。:praise:


主要的知识点有  指针  数组  大小端……。




  1. #include <stdio.h>
  2. int main()
  3. {
  4.     unsigned long count1 = 0xFFFFFFFF;                           //记录本次的捕获值

  5.         printf("%x\n",count1);        
  6.         unsigned char *q = &count1;


  7.         *(q) = 0x12;
  8.         *(q+1) = 0x34;
  9.         *(q+2) = 0x56;
  10.         *(q+3) = 0x78;
  11.         printf("%x\n",count1);


  12.         q[0]= 0xAA;
  13.         q[1]= 0xBB;
  14.         q[2]= 0xCC;
  15.         q[3]= 0xDD;

  16.         printf("%x\n",count1);




  17.         ((unsigned char *)&count1)[3] = 0x12;   
  18.         ((unsigned char *)&count1)[2] = 0x34;
  19.         ((unsigned char *)&count1)[1] = 0x56;
  20.         ((unsigned char *)&count1)[0] = 0x78;
  21.         
  22.         printf("%x\n",count1);

  23.         
  24. }
复制代码
下面是一个B站的讲解,看完就理解了。
https://www.bilibili.com/video/BV1mx411d7PA



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
回复 支持 反对

使用道具 举报

发表于 2020-10-19 04:45:47 | 显示全部楼层
        ((unsigned char *)&count1)[3] = CCAP0L;
        ((unsigned char *)&count1)[2] = CCAP0H;
        ((unsigned char *)&count1)[1] = cnt;
        ((unsigned char *)&count1)[0] = 0;
        
        只看等号前的部分,这里用到C语言的语法知识:
        1. &count1 --> 取count1的地址,也就是指向count1的指针;
        2. ((unsigned char *)&count1) --> 把这个指针强制转换成 (unsigned char *)类型的指针,使编译器知道指向目标的单位长度是“1个字节”;
        3. 指针与数组的写法都可以给某个地址的内存赋值,例如:
           char a[3];
           char *p = &a;
           则:
           p 等同于 &a[0], p + 1 等同于 &a[1], p + 2 等同于 &a[2], p + 3 等同于 &a[3].
           那么,*p 就是 a[0], *(p + 1) 就是 a[1], *(p + 2) 就是 a[2], *(p + 3) 就是 a[3].
           
        指针与数组都可以表示某个地址,明白了吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-20 07:54:08 | 显示全部楼层
谢谢大家,全部代码如下
  1. #include "reg51.h"
  2. #include "intrins.h"

  3. //测试工作频率为11.0592MHz

  4. sfr     CCON        =   0xd8;
  5. sbit    CF          =   CCON^7;
  6. sbit    CR          =   CCON^6;
  7. sbit    CCF3        =   CCON^3;
  8. sbit    CCF2        =   CCON^2;
  9. sbit    CCF1        =   CCON^1;
  10. sbit    CCF0        =   CCON^0;
  11. sfr     CMOD        =   0xd9;
  12. sfr     CL          =   0xe9;
  13. sfr     CH          =   0xf9;
  14. sfr     CCAPM0      =   0xda;
  15. sfr     CCAP0L      =   0xea;
  16. sfr     CCAP0H      =   0xfa;
  17. sfr     PCA_PWM0    =   0xf2;
  18. sfr     CCAPM1      =   0xdb;
  19. sfr     CCAP1L      =   0xeb;
  20. sfr     CCAP1H      =   0xfb;
  21. sfr     PCA_PWM1    =   0xf3;
  22. sfr     CCAPM2      =   0xdc;
  23. sfr     CCAP2L      =   0xec;
  24. sfr     CCAP2H      =   0xfc;
  25. sfr     PCA_PWM2    =   0xf4;
  26. sfr     CCAPM3      =   0xdd;
  27. sfr     CCAP3L      =   0xed;
  28. sfr     CCAP3H      =   0xfd;
  29. sfr     PCA_PWM3    =   0xf5;

  30. unsigned char cnt;                              //存储PCA计时溢出次数
  31. unsigned long count0;                           //记录上一次的捕获值
  32. unsigned long count1;                           //记录本次的捕获值
  33. unsigned long length;                           //存储信号的时间长度

  34. void PCA_Isr() interrupt 7
  35. {
  36.     if (CF)
  37.     {
  38.         CF = 0;
  39.         cnt++;                                  //PCA计时溢出次数+1
  40.     }
  41.     if (CCF0)
  42.     {
  43.         CCF0 = 0;
  44.         count0 = count1;                        //备份上一次的捕获值
  45.         ((unsigned char *)&count1)[3] = CCAP0L;
  46.         ((unsigned char *)&count1)[2] = CCAP0H;
  47.         ((unsigned char *)&count1)[1] = cnt;
  48.         ((unsigned char *)&count1)[0] = 0;
  49.         length = count1 - count0;              //length保存的即为捕获的脉冲宽度
  50.     }
  51. }

  52. void main()
  53. {
  54.     cnt = 0;                                    //用户变量初始化
  55.     count0 = 0;
  56.     count1 = 0;
  57.     length = 0;
  58.     CCON = 0x00;
  59.     CMOD = 0x09;                                //PCA时钟为系统时钟,使能PCA计时中断
  60.     CL = 0x00;
  61.     CH = 0x00;
  62.     CCAPM0 = 0x11;                              //PCA模块0为16位捕获模式(下降沿捕获)
  63.     CCAPM0 = 0x21;                              //PCA模块0为16位捕获模式(下降沿捕获)
  64.     CCAPM0 = 0x31;                              //PCA模块0为16位捕获模式(下降沿捕获)
  65.     CCAP0L = 0x00;
  66.     CCAP0H = 0x00;
  67.     CR = 1;                                     //启动PCA计时器
  68.     EA = 1;

  69.     while (1);
  70. }

复制代码


方括号一般代指数组下标,这里并没有定义过数组,怎么就直接引用了?
回复 支持 反对

使用道具 举报

发表于 2020-10-20 19:07:52 | 显示全部楼层
count1定义为ulong,就是四个字节无符号。
&count1取其地址,强制转换到uchar*指针,得到一个uchar的指针,当然可以通过[]取索引为0~3的一个字节。
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-10 05:18 , Processed in 0.171601 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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