注册 登录
查看: 2233|回复: 28

结构体指针与PORT

[复制链接]
发表于 2014-10-28 22:01:21 | 显示全部楼层 |阅读模式
本帖最后由 ii童话Bū说话 于 2014-10-30 21:15 编辑

首先感谢 仰逸致山外哥 的帮助!!!

/***************************************************************************************************************/
以下摘自谭浩强C程序设计第四版
9.3.1指向结构体变量的指针
    指向结构体对象的指针变量既可指向结构体变量,也可指向结构体数组中的元素。指针变量的基类型必须与结构体变量的类型相同。例如:
struct Student * pt;  //pt可以指向struct Student类型的变摄或数组元素先通过一个例子了解什么是指向结构体变量的指针变量以及怎样使用它。
例9.5通过指向结构体变量的指针变量输出结构体变量中成员的信息。
解题思路:在已有的基础上,本题要解决两个向题:
(1)怎样对结构体变量成员赋值;
(2)怎样通过指向结构体变量的指针访问结构体变量中成员。
编写程序:
  1. #include <stdio.h>
  2. #include <string.h>
  3. int main( )
  4. {
  5.   struct Student
  6.   {
  7.     long num;
  8.     char name[20];
  9.     char sex;
  10.     float score;
  11.   };
  12.   struct Student stu_1;           //定义struct Student类型的变最stu_1
  13.   struct Student *p;             //定义指向:truct Student类型数据的指针变童P
  14.   p=&stu_1;                        //P指向stu_1
  15.   stu_1.num=10101;                //对结构体变里的成员斌值
  16.   strcpy(stu_1.name,"Li Lin");  //用字符申复制函数给stu_1.name斌值
  17.   stu_1.sex='M';
  18.   stu_1.score= 89.5;
  19.   printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n",
  20.   stu_1.num,stu_1.name,stu_1.sex,stu_1.score);
  21.   printf("\nNo.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n",
  22.   (*p).num,(*p).name,(*p).sex,(*p).score);
  23.   return 0;
  24. }

运行结果
在山外哥出的神书中刚开始看到 -> 的时候,不知道是什么东西,平时很少用到。后来查了一下书才知道是结构体指针!
在谭浩强的书中这样写着!
    说明:为了使用方便和直观,C语言允许把(* p).num用p->num来代替,“->”代
表一个箭头,p->num表示p所指向的结构体变量中的num成员。同样,(*p).name等
价于p->name,“->”称为指向运算符.
    如果p指向一个结构体变量stu,以下3种用法等价:
    ① stu.成员名(如stu. num) ;
    ②(*p).成员名(如(*p).num);
    ③ p->成员名(如p->num)。

下面举个简单的例子来说明一下
  1. #include<stdio.h>
  2. typedef struct stu
  3. {
  4.     int num;
  5.     char *name;
  6.     char sex;
  7.     float score;
  8. }pstu;
  9. main()
  10. {
  11.   stu boy1={102,"Zhang ping",'M',78.5};
  12.     pstu *p;
  13.     p = &boy1;
  14.     printf(" Number = %d  \n Name  = %s  \n",  boy1.num,  boy1.name);
  15.     printf(" Sex    = %c  \n Score = %f  \n\n",  boy1.sex,  boy1.score);
  16.     printf(" Number = %d  \n Name  = %s  \n",  (*p).num,(*p).name  );
  17.     printf(" Sex    = %c  \n Score = %f  \n\n",  (*p).sex,(*p).score  );
  18.     printf(" Number = %d  \n Name  = %s  \n",  p->num,  p->name  );
  19.     printf(" Sex    = %c  \n Score = %f  \n\n",  p->sex,  p->score);
  20. }


运行结果如图所示

结果已经很明显了!/
boy1.num 等价于 (*p).num 等价于 p->num
这样一来就知道用法了!


在山外哥的书中有这样的宏定义
  1. #define PORT_PCR_REG(base,index)  ((base) -> PCR[index])
  2. #define PORT_GPCLR_REG(base)    ((base) -> GPCLR)
  3. #define PORT_GPCHR_REG(base)    ((base) -> GPCHR)
  4. #define PORT_ISFR_REG(base)      ((base) -> ISFR)
  5. #define PORT_DFER_REG(base)      ((base) -> DFER)
  6. #define PORT_DFCR_REG(base)      ((base) -> DFCR)
  7. #define PORT_DFWR_REG(base)      ((base) -> DFWR)
宏定义的目的就是,方便使用与记忆。用容易记的名字来代替!
而在下面的函数中定义了地址,可以传入
  1. #define PORTA_BASE_PTR     ((PORT_MemMapPtr)0x4004900u)
  2. #define PORTB_BASE_PTR     ((PORT_MemMapPtr)0x4004A00u)
  3. #define PORTC_BASE_PTR     ((PORT_MemMapPtr)0x4004B00u)
  4. #define PORTD_BASE_PTR    ((PORT_MemMapPtr)0x4004C00u)
  5. #define PORTE_BASE_PTR     ((PORT_MemMapPtr)0x4004D00u)
PORT_DFWR_REG(PORTE_BASE_PTR )
展开为
PORTE_BASE_PTR -> DFWR
(PORT_MemMapPtr)0x4004D00u -> DFWR

说明:((PORT_MemMapPtr)0x4004D00u)类似于(int*)+地址,即让指针指向的内存地址


下面是我自己不懂的时候敲得一些代码,不知道有没有有错误的地方!
如有错误,望各位大神批评指正!这也是我发帖的目的!

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<stdint.h>

  4. //在C编译器里测试的
  5. #define PORTA_BASE_PTR ((PORT_MemMapPtr)0x402000)
  6. #define PORTB_BASE_PTR ((PORT_MemMapPtr)0x4020cc)
  7. #define PORTC_BASE_PTR ((PORT_MemMapPtr)0x402198)
  8. #define PORTD_BASE_PTR ((PORT_MemMapPtr)0x402264)
  9. #define PORTE_BASE_PTR ((PORT_MemMapPtr)0x402330)

  10. #define A 0
  11. #define B 1
  12. #define C 2
  13. #define D 3
  14. #define E 4
  15. #define MAX 5

  16. #define PORT_PCR_REG(base,index)  ((base) -> PCR[index])
  17. #define PORT_GPCLR_REG(base)    ((base) -> GPCLR)
  18. #define PORT_GPCHR_REG(base)    ((base) -> GPCHR)
  19. #define PORT_ISFR_REG(base)      ((base) -> ISFR)
  20. #define PORT_DFER_REG(base)      ((base) -> DFER)
  21. #define PORT_DFCR_REG(base)      ((base) -> DFCR)
  22. #define PORT_DFWR_REG(base)      ((base) -> DFWR)

  23. #define PORT_RESERVRD_0_REG(a,b)      ((a) -> RESERVRD_0[b])

  24. typedef struct  PORT_MemMap
  25. {
  26.   uint32_t  PCR[32];
  27.   uint32_t  GPCLR;
  28.   uint32_t  GPCHR;
  29.   uint8_t    RESERVRD_0[24];
  30.   uint32_t  ISFR;
  31.   uint8_t    RESERVRD_1[28];
  32.   uint32_t  DFER;
  33.   uint32_t  DFCR;
  34.   uint32_t  DFWR;
  35. }volatile *PORT_MemMapPtr;
  36.   
  37. /******************************************************************/
  38. /*        用这个结构体数组替代宏定义 (假装寄存器)               */
  39. struct  PORT_MemMap PORTx_BASE_PTR[MAX]=
  40. {
  41.   {
  42.     1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
  43.     33,
  44.     34,
  45.     35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,
  46.     59,
  47.     60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,
  48.     88,
  49.     89,
  50.     90,  
  51.   },
  52.   {100,101,102,103,104,105,106},
  53.   {200,201,202,203,204,205,206},
  54.   {300,301,302,303,304,305,306},
  55.   {{},400}
  56. };
  57. /*******************************************************************/
  58.   
  59. int main()
  60. {  
  61.   PORT_MemMapPtr p;
  62.   p=&PORTx_BASE_PTR[0];
  63.   
  64.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A]));      
  65.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].GPCLR));  
  66.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].GPCHR));  
  67.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].RESERVRD_0[0]));
  68.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].ISFR));   
  69.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].RESERVRD_1[0]));
  70.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].DFER));   
  71.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].DFCR));   
  72.   printf(" ADD = %x  \n" ,  &(PORTx_BASE_PTR[A].DFWR));   
  73.   printf("\n");
  74.   printf(" B_ADD = %x  \n" ,  &(PORTx_BASE_PTR[B]));      
  75.   printf(" C_ADD = %x  \n" ,  &(PORTx_BASE_PTR[C]));      
  76.   printf(" D_ADD = %x  \n" ,  &(PORTx_BASE_PTR[D]));        
  77.   printf(" E_ADD = %x  \n" ,  &(PORTx_BASE_PTR[E]));        
  78.   
  79.   printf(" Number = %d  \n" ,  p ->PCR[1]);
  80.   printf(" Number = %d  \n" ,  p ->ISFR);
  81.   printf(" Number = %d  \n" ,  p ->DFWR);
  82.   printf(" Number = %d  \n" ,  (++p) ->PCR[2]);
  83.   printf("\n");
  84.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->PCR[0]);
  85.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->GPCLR  );
  86.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->GPCHR  );
  87.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->ISFR  );
  88.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->DFER  );
  89.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->DFCR  );
  90.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[A])->DFWR  );
  91.   printf("\n");
  92.   printf(" Number = %d  \n" ,  (&PORTx_BASE_PTR[E])->GPCLR);
  93.   printf("\n");
  94.   printf(" Number = %d  \n" ,  PORT_PCR_REG  ((&PORTx_BASE_PTR[A]),3));
  95.   printf(" Number = %d  \n" ,  PORT_GPCLR_REG  (&PORTx_BASE_PTR[A])  );
  96.   printf(" Number = %d  \n" ,  PORT_GPCHR_REG  (&PORTx_BASE_PTR[A])  );
  97.   printf(" Number = %d  \n" ,  PORT_ISFR_REG  (&PORTx_BASE_PTR[A])  );
  98.   printf(" Number = %d  \n" ,  PORT_DFER_REG  (&PORTx_BASE_PTR[A])  );
  99.   printf(" Number = %d  \n" ,  PORT_DFCR_REG  (&PORTx_BASE_PTR[A])  );
  100.   printf(" Number = %d  \n" ,  PORT_DFWR_REG  (&PORTx_BASE_PTR[A])  );
  101.   printf(" Number = %d  \n" ,  PORT_RESERVRD_0_REG((&PORTx_BASE_PTR[A]),0));
  102.   printf("\n");  
  103.   printf(" Number = %d  \n" ,  PORT_PCR_REG  ((PORTA_BASE_PTR),3));
  104.   printf(" Number = %d  \n" ,  PORT_GPCLR_REG  (PORTA_BASE_PTR)  );
  105.   printf(" Number = %d  \n" ,  PORT_GPCHR_REG  (PORTA_BASE_PTR)  );
  106.   printf(" Number = %d  \n" ,  PORT_ISFR_REG  (PORTA_BASE_PTR)  );
  107.   printf(" Number = %d  \n" ,  PORT_DFER_REG  (PORTA_BASE_PTR)  );
  108.   printf(" Number = %d  \n" ,  PORT_DFCR_REG  (PORTA_BASE_PTR)  );
  109.   printf(" Number = %d  \n" ,  PORT_DFWR_REG  (PORTA_BASE_PTR)  );
  110. }
运行结果




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

本帖被以下淘专辑推荐:

回复

使用道具 举报

发表于 2014-10-28 22:11:52 | 显示全部楼层
追根究底,是学习最需要的品质。
回复 支持 反对

使用道具 举报

发表于 2014-10-28 22:17:26 | 显示全部楼层
谢谢楼主分享,学习了。谢谢山外哥的技术支持
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-10-28 22:50:50 | 显示全部楼层
山外メ雲ジ 发表于 2014-10-28 22:11
追根究底,是学习最需要的品质。

哪里啊!只不过人比较本而已!还有!山外哥啊!字数限制10000有点少额!
来自苹果客户端来自苹果客户端
回复 支持 反对

使用道具 举报

发表于 2014-10-28 22:53:01 | 显示全部楼层
ii童话Bū说话 发表于 2014-10-28 22:50
哪里啊!只不过人比较本而已!还有!山外哥啊!字数限制10000有点少额!

嗯,论坛规则,还需要根据你们的意见反馈来修改一下。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-10-30 20:40:47 | 显示全部楼层
山外メ雲ジ 发表于 2014-10-28 22:53
嗯,论坛规则,还需要根据你们的意见反馈来修改一下。

啊喔!又被收录了!
回复 支持 反对

使用道具 举报

发表于 2014-10-30 20:41:49 | 显示全部楼层

很多初学者都有这疑问嘛,比较好的帖子,当然得收录啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-10-30 21:09:47 | 显示全部楼层
山外メ雲ジ 发表于 2014-10-30 20:41
很多初学者都有这疑问嘛,比较好的帖子,当然得收录啊

以修改完!望批阅!
回复 支持 反对

使用道具 举报

发表于 2014-10-30 21:11:20 | 显示全部楼层

总有一天,你绝对是大牛,做技术追求追根到底
回复 支持 反对

使用道具 举报

发表于 2014-10-30 21:14:26 | 显示全部楼层
仰逸致 发表于 2014-10-30 21:11
总有一天,你绝对是大牛,做技术追求追根到底

同感,你也是大牛级别啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-10-30 21:14:47 | 显示全部楼层
仰逸致 发表于 2014-10-30 21:11
总有一天,你绝对是大牛,做技术追求追根到底

呃!谬赞了!自己比较菜!只能多练习了!
回复 支持 反对

使用道具 举报

发表于 2014-12-6 18:31:08 | 显示全部楼层
((PORT_MemMapPtr)0x4004D00u)类似于(int*)+地址,即让指针指向的内存地址

这句话是说指针的地址是0x4004D00u,还是说指针指向的内容的地址是0x4004D00u
回复 支持 反对

使用道具 举报

发表于 2014-12-10 21:11:53 | 显示全部楼层
#define PORTA_BASE_PTR     ((PORT_MemMapPtr)0x4004900u)
说明:((PORT_MemMapPtr)0x4004900u)类似于(int*)+地址,即让指针指向的内存地址
个人理解这句话的意思是把地址单元0x4004900u强制转换为指针,通过宏定义方式传递给PORTA_BASE_PTR,跟楼主的意思一样
山外哥,对吗    麻烦出个帖子介绍一下结构体指针,就像玄来玄去介绍枚举的帖子
回复 支持 反对

使用道具 举报

发表于 2014-12-10 21:32:08 | 显示全部楼层
bieshuono 发表于 1418217113
#define PORTA_BASE_PTR     ((PORT_MemMapPtr)0x4004900u)
说明:((PORT_MemMapPtr)0x4004900u)类似于(int*)+地址,即让指针指向的内存地址
个人理解这句话的意思是把地址单元0x4004900u强制转换为指针,通过宏定义方式传递给PORTA_BASE_PTR,跟楼主的意思一样
山外哥,对吗    麻烦出个帖子介绍一下结构体指针, ...
是的,就是强制类型转换,让编译器知道如何处理这地址的内容。
来自PC客户端 来自PC客户端
回复 支持 反对

使用道具 举报

发表于 2014-12-10 21:32:46 | 显示全部楼层
热血不应该 发表于 1417861868
((PORT_MemMapPtr)0x4004D00u)类似于(int*)+地址,即让指针指向的内存地址

这句话是说指针的地址是0x4004D00u,还是说指针指向的内容的地址是0x4004D00u?
是指针指向的地址
来自PC客户端 来自PC客户端
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-12-10 21:39:41 | 显示全部楼层
山外メ雲ジ 发表于 2014-10-30 21:14
同感,你也是大牛级别啊

两位大神就不要笑话我啦!
回复 支持 反对

使用道具 举报

发表于 2015-1-10 16:43:40 | 显示全部楼层
666666666666666666
回复 支持 反对

使用道具 举报

发表于 2015-1-21 23:02:36 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2015-4-16 15:23:14 | 显示全部楼层
想请教一下如果结构体那里不加 volatile 关键字会怎么样呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-19 22:01:07 | 显示全部楼层
ggttkl 发表于 1429168994
想请教一下如果结构体那里不加 volatile 关键字会怎么样呢?
数据更新不会及时哈!有的时候还会编译器优化掉!前两天刚遇到这个情况!定义的变量被编译器优化掉了!
来自PC客户端 来自PC客户端
回复 支持 反对

使用道具 举报

发表于 2015-9-4 21:02:22 | 显示全部楼层
受教了
回复 支持 反对

使用道具 举报

发表于 2015-9-4 21:47:24 | 显示全部楼层
PORT_ISFR_REG(base)这个是什么意思?小白不好意思啊
回复 支持 反对

使用道具 举报

发表于 2015-9-4 22:05:36 | 显示全部楼层
insurance 发表于 2015-9-4 21:47
PORT_ISFR_REG(base)这个是什么意思?小白不好意思啊

就是一个宏而已,具体的意思,你看山外的视频,有讲如何看寄存器的那部分讲的
回复 支持 反对

使用道具 举报

发表于 2015-9-18 12:37:45 | 显示全部楼层
谢谢
回复 支持 反对

使用道具 举报

发表于 2015-12-3 20:45:02 | 显示全部楼层
66666
回复 支持 反对

使用道具 举报

发表于 2015-12-18 21:49:29 | 显示全部楼层
感觉很有用哎,顶一个,
回复 支持 反对

使用道具 举报

发表于 2016-1-20 18:49:37 | 显示全部楼层
赞一个
回复 支持 反对

使用道具 举报

发表于 2016-1-21 19:23:17 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2016-3-10 09:47:53 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

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

本版积分规则

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