怎么仿照STM32库文件来写STM32驱动文件

2019-04-15 12:26发布

1、这天在折腾STM32,看到很多高手写的一些程序,记录一下,作为以后自己编写高质量软件代码的参照,      (1)    #define   rUTXH0     (*(volatile unsigned char *)0x1d00020)     //代码比如这是ARM头文件中经常看到的宏定义,UTXH0是寄存器, 这个语句具体是什么意思?以前有过PIC单片机的基础,在编写PIC程序的时候 ,比如像读取给PORTA寄存器赋值,不用任何定义直接 PORTA=XX就可以了,为什么在ARM还要这样定义  而且定义的这么复杂,为什么不能像单片机那样直接用吗? 答案:嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址。不进行宏定义的话就得每次用的时候用地址了,那是麻烦的操作,另外容易把地址搞错(例如出现的笔误现象),使用宏定义的话可以直接进行替换,关于这个定义,是个地址,那么按照C语言的语法规则,这个表示地址的量应该是指针类型,所以,知道要访问的内存地址后,比如访问地址为0x5F,要进行如下的步骤:第一步:要把它强制转换为指针类型----(unsigned char *)0x5F,关于为什么是unsigned char类型的,AVRSREG是八位寄存器,所以0x5F强制转换为指向unsigned char类型,在STM32中的寄存器是32位的所以要强制转换为unsigned long类型的。volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了(参考STM32 运行机制,是把ROM里的数据拷贝到RAM中,由于编译器的优化,有些变量是使用的备份,而不是RAM中的数据,有时候RAM会由于中断改变数据)。这种意想不到地改变,不是由程序去改变,而是由硬件去改变——意想不到,使用的是ROM中的原始值,
第二步:对指针变量解引用,就能操作指针所指向的地址的内容了,*(volatile unsigned char *)0x5F就是取地址中的内容
第三步:小心地把#define宏中的参数用括号括起来,这是一个很好的习惯,所以#define SREG     (*(volatile unsigned char *)0x5F),类似的,如果使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义#define RAM_ADDR      (*(volatile unsigned long   *)0x0000555F),然后就可以用C语言对这个内存地址进行读写操作了
    
读:tmp = RAM_ADDR
    
写:RAM_ADDR = 0x55
#define U0RBR (*((volatile unsigned char *) 0xE000C000))
这个在单片机里很常见,
((volatile unsigned char *) 0xE000C000) 是将0xE000C000强制转换为保存可能随时更新无符号字符型数据的地址,前面又加了*,是表示指向这个地址里面的值,这与其他普通定义的指针一样了,如charx,y,*p;p=&x;*p=y;y=*p就如同一个变量一样,既可以从这里读出值,也可以给被赋值,这里需要注意的是,这个地址值里的东西是不是既可以读又可以写,这个在datasheet应该有定义,或者看程序中都拿他干什么。#define U0RBR (*((volatile unsigned char *) 0xE000C000)) 这个是宏定义,即UORBR替换(*((volatile unsigned char*) 0xE000C000)),宏定义是为了程序书写方便,因为在程序中可能有好多地方要使用(*((volatile unsigned char*) 0xE000C000)),在用时,总要写这么多东西麻烦。