- C工程与寄存器封装
- 1 C语言工程简介
- 2 启动文件
- 3 C语言实现LED闪烁
- 3.1 C语言与汇编分别是怎么 *** 作寄存器的
- 3.2 用C语言实现LED闪烁
- 4 寄存器的封装
- 4.1 第一种封装方式(宏定义)
- 4.2 第二种封装方式(结构体加宏定义)
- 5 寄存器的标准化 *** 作
- 5.1 C语言位 *** 作复习
- 5.2改进代码
common文件夹下是头文件和.c文件 。
start 是启动文件
interface.c是主函数所在文件。
直接用就🆗
主要做以下 *** 作
异常向量表所使用地址空间占用(防止其它代码占用)
修改异常向量表地址位置(通过协处理器 cp15)
设置模式为SVC模式,禁止FIO/IRQ(执行重要上电的代码)
关闭MCR,TlLBs
使能计算浮点型协处理器。
关闭MMU
初始化栈
跳转到main
1 .text
2 .global _start
3 _start:
4 /*
5 * Vector table
6 */
7 b reset
8 b .
9 b .
10 b .
11 b .
12 b .
13 b .
14 b .
15
16 reset:
17 /*
18 * Set vector address in CP15 VBAR register
19 */
20 ldr r0, =_start
21 mcr p15, 0, r0, c12, c0, 0 @Set VBAR
22
23 /*
24 * Set the cpu to SVC32 mode, Disable FIQ/IRQ
25 */
26 mrs r0, cpsr
27 bic r0, r0, #0x1f
28 orr r0, r0, #0xd3
29 msr cpsr ,r0
30
31 /*
32 * Defines access permissions for each coprocessor
33 */
34 mov r0, #0xfffffff
35 mcr p15, 0, r0, c1, c0, 2
36
37 /*
38 * Invalidate L1 I/D
39 */
40 mov r0, #0 @Set up for MCR
41 mcr p15, 0, r0, c8, c7, 0 @Invalidate TLBs
42 mcr p15, 0, r0, c7, c5, 0 @Invalidate icache
43
44 /*
45 * Set the FPEXC EN bit to enable the FPU
46 */
47 mov r3, #0x40000000
48 fmxr FPEXC, r3
49
50 /*
51 * Disable MMU stuff and caches
52 */
53 mrc p15, 0, r0, c1, c0, 0
54 bic r0, r0, #0x00002000 @Clear bits 13 (--V-)
55 bic r0, r0, #0x00000007 @Clear bits 2:0 (-CAM)
56 orr r0, r0, #0x00001000 @Set bits 12 (---I)Icache
57 orr r0, r0, #0x00000002 @Set bits 1 (--A-)Align
58 orr r0, r0, #0x00000800 @Set bits 1 (Z---)BTB
59 mcr p15,0,r0,c1,c0,0
60
61 /*
62 *Initialize stacks
63 */
64init_stack:
65 /*svc mode stack*/
66 msr cpsr, #0xd3
67 /*加等号是把地址给sp 不加等号是把地址的内容给sp*/
68 ldr sp, _stack_svc_end
69
70 /*undef mode stack*/
71 msr cpsr, #0xdb
72 ldr sp, _stack_und_end
73
74 /*abort mode stack*/
75 msr cpsr,#0xd7
76 ldr sp,_stack_abt_end
77
78 /*irq mode stack*/
79 msr cpsr,#0xd2
80 ldr sp, _stack_irq_end
81
82 /*fiq mode stack*/
83 msr cpsr,#0xd1
84 ldr sp, _stack_fiq_end
85
86 /*user mode stack, enable FIQ/IRQ*/
87 msr cpsr,#0x10
88 ldr sp, _stack_usr_end
89
90 /*Call main*/
91 b main
92 /*使用的是满减栈所以栈指针起始地址要先偏移512*/
93 _stack_svc_end:
94 .word stack_svc + 512
95 _stack_und_end:
96 .word stack_und + 513
97 _stack_abt_end:
98 .word stack_abt + 512
99 _stack_irq_end:
100 .word stack_irq + 512
101 _stack_fiq_end:
102 .word stack_fiq + 512
103 _stack_usr_end:
104 .word stack_usr + 512
105
106 /*申请各个模式下的栈空间*/
107 .data
108 stack_svc:
109 .space 512
110 stack_und:
111 .space 512
112 stack_abt:
113 .space 512
114 stack_irq:
115 .space 512
116 stack_fiq:
117 .space 512
118 stack_usr:
119 .space 512
3 C语言实现LED闪烁
3.1 C语言与汇编分别是怎么 *** 作寄存器的
- 汇编语言访问寄存器
(1)读寄存器
LDR R1,[R2]
(2)写寄存器
STR R1,[R2] - C语言访问寄存器
(1)读寄存器
data=*ADDR
(2)写寄存器
ADDR =data
详细讲解GPIO *** 作
12 void Delay(unsigned int Time)
13 {
14 while(Time--);
15 }
16 int main()
17 {
18
19 /*设置GPX2CON寄存器将CPX2_7引脚设置成输出模式*/
20 /*写寄存器*/
21 /*注意0x11000c40为一地址常量(常量前同样可以加*) */
22 /*这里需要告诉编译器这是什么类型的地址常量,在这里强制转化为无符号整型*/
23 *((unsigned int*)0x11000c40) = 0x10000000;
24
25 while(1)
26 {
27 /*点亮LED*/
28 /* *** 作GPX2DAT寄存器*/
29 *(unsigned int *)0x11000c44 =0x00000080;
30 Delay(1000000);
31 /*熄灭LED*/
32 *(unsigned int *)0x11000c44 =0x00000000;
33 Delay(1000000);
34
35 }
36
37 return 0;
38 }
4 寄存器的封装
上面的代码不太适合阅读和维护。所以要对其加以封装
4.1 第一种封装方式(宏定义) 41 #define GPX2CON *((unsigned int*)0x11000c40) //寄存器地址
42 #define GPX2DAT *((unsigned int *)0x11000c44) //寄存器地址
12 void Delay(unsigned int Time)
13 {
14 while(Time--);
15 }
44 int main()
45 {
46 /*GPIO设置为输出模式*/
47 GPX2CON=0x10000000;
48
49 while(1)
50 {
51 /*点亮LED*/
52 /* *** 作GPX2DATA寄存器*/
53 GPX2DAT=0x00000080;
54 Delay(1000000);
55 /*熄灭LED*/
56 GPX2DAT =0x00000000;
57 Delay(1000000);
58
59 }
60 }
4.2 第二种封装方式(结构体加宏定义)
12 void Delay(unsigned int Time)
13 {
14 while(Time--);
15 }
63 typedef struct
64 {
65
66 unsigned int CON;
67 unsigned int DAT;
68 unsigned int PUD;
69 unsigned int DRV;
70 }gpx2;
71 #define GPX2 (*(gpx2*)0x11000c40) //结构体的成员在内存当中的存储位置是连续的
72 int main()
73 {
74 GPX2.CON=0x10000000;
75 while(1)
76 {
77 GPX2.DAT = 0x00000080;
78 Delay(1000000);
79 GPX2.DAT = 0x00000000;
80 Delay(1000000);
81
82 }
83 }
5 寄存器的标准化 *** 作
上面的寄存器 *** 作有局限性,比如 GPX2.DAT = 0x00000080; 我只想 *** 作GPX2_7这个IO,结果把
整组IO口都 *** 作了。
例子:unsigned int a;将a的第三位置1,其它位保持不变。
a=a | (1<<3);
unsigned int a;将a的第三位置0,其它位保持不变。
a=a & (~(1<<3))
unsigned int a;将a的第[7:4]置为0101,其它位保持不变(分为两步)。
(1)先清零([7:4])
11111111 11111111 11111111 00001111
这个数由
00000000 00000000 00000000 00001111
左移4位
00000000 00000000 00000000 11110000
在按位取反得到
即 a=a & (~(0xF<<4))
(2) 再置位
00000000 00000000 00000000 01010000
这个数由
00000000 00000000 00000000 00000101
左移4位得到
即 a=a | (0x5<<4)
所以 unsigned int a;将a的第[7:4]置为0101,其它位保持不变(分为两步)。
为a= a & (~(0xF<<4)) | (0x5<<4);
根据上述知识,对4.2的代码加以改进如下:
5.2改进代码 12 void Delay(unsigned int Time)
13 {
14 while(Time--);
15 }
63 typedef struct
64 {
65
66 unsigned int CON;
67 unsigned int DAT;
68 unsigned int PUD;
69 unsigned int DRV;
70 }gpx2;
71 #define GPX2 (*(gpx2*)0x11000c40) //结构体的成员在内存当中的存储位置是连续的
72 int main()
73 {
74 GPX2.CON=GPX2.CON & (~(0xF <<28 )) | (0x1 << 28);//(寄存器的[31,28](设为输出模式))
75 while(1)
76 {
77 GPX2.DAT = GPX2.DAT|(1<<7);//(第7位为设置为高电平)
78 Delay(1000000);
79 GPX2.DAT = GPX2.DAT &(~(1<<7));//(第7位为设置为低电平)
80 Delay(1000000);
81
82 }
83 }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)