第三篇---STM32灵魂塑造之呱呱坠地

原创 2012年03月30日 22:29:06

      之前我从宏观上介绍了CM3架构和STM32的相关内容,现在我们就开始正式进行STM32的灵魂塑造---程序编写。为什么说是塑造,因为整个代码是从无到有的而非利用官方库的开发,就好像新生的婴儿呱呱坠地。。。罗嗦止于此,切入正题!

      在我的一篇文章《ARM寄存器C操作探讨》里,我曾详细的介绍了ARM通常采用的两种寄存器C操作的方式,现在我们就实际应用一下第二种方法。为了帮初学者形成ARM编程的一般思路和思想,我会从解读Datasheet到实际编程都说明的非常详细。

      首先,我们要读Datasheet,这里我选用的芯片是STM32F103RB,大家可以到ST的官网寻找下载,读Datasheet读什么?就像物质是由原子组成,程序是由寄存器的配置组成,尤其对ARM来说,灵活的配置寄存器是基础中的基础,说来容易,可至此还是有种无从下手的感觉,下面我就从寄存器操作开始讲讲构建自己的ARM编程模式。

      打开KEIL,新建一个工程,device选择STM32F103RB,详细的我这里不再展开,相信大家在51或其它微处理器的学习中都用的熟的不能再熟,不赘述,直奔核心---寄存器的操作。要操作一个寄存器我们得知道这个寄存器的地址,如何寻址?这就是重点。我们需要查看Datasheet来确定STM32F103RB这个芯片或者说STM32F103系列芯片的寄存器映射。依据这个内存映射,我们可以找到芯片外设的首地址,而这正是我们想要的、需要的。那么具体怎么写?我们新建一个名为MYstm32f10x_map.h的文件,内容可以这么写:

     

#ifndef MYstm32f10x_map_h_h_
#define MYstm32f10x_map_h_h_

//数据类型定义
typedef unsigned int  uint32;
typedef unsigned short int uint16;

//####################################################################################
//****RCC REGS******//
//####################################################################################

typedef struct tagRCC_REGS{
	uint32 CR;       //时钟控制寄存器
	uint32 CFGR;     //时钟配置寄存器
	uint32 CIR;      //时钟中断寄存器
	uint32 APB2RSTR; //APB2外设复位寄存器
	uint32 APB1RSTR; //APB1外设复位寄存器
	uint32 AHBENR;   //AHB外设时钟使能寄存器
	uint32 APB2ENR;  //APB2外设时钟使能寄存器
	uint32 APB1ENR;  //APB1外设时钟使能寄存器
	uint32 BDCR;     //备份域控制寄存器
	uint32 CSR;      //控制/状态寄存器
}RCC_REGS;

#define RCC ((volatile RCC_REGS *)0x40021000)    //RCC寄存器组首地址

//####################################################################################
//****GPIO REGS****//
//####################################################################################

typedef struct tagGPI0X_REGS{	 //X=A\B\C
	uint32 CRL;  //端口配置低寄存器
	uint32 CRH;  //端口配置高寄存器
	uint32 IDR;  //端口输入数据寄存器
	uint32 ODR;  //端口输出数据寄存器
	uint32 BSRR; //端口位设置/清除寄存器
	uint32 BRR;  //端口位清除寄存器
	uint32 LCKR; //端口配置锁定寄存器
}GPIOX_REGS;

#define GPIOA ((volatile GPIOX_REGS *)0x40010800)	 //端口A寄存器组首地址
#define GPIOB ((volatile GPIOX_REGS *)0x40010C00)	 //端口B寄存器组首地址
#define GPIOC ((volatile GPIOX_REGS *)0x40011000)	 //端口C寄存器组首地址

//####################################################################################
//*****TIME REGS******//
//####################################################################################

typedef struct tagADVANCED_TIMX_REGS{		  //高级控制定时器(X)寄存器组
	uint32 CR1;      //控制寄存器1
	uint32 CR2;      //控制寄存器2
	uint32 SMCR;     //从模式控制寄存器
	uint32 DIER;     //中断使能寄存器
	uint32 SR;       //状态寄存器
	uint32 EGR;      //事件产生寄存器
	uint32 CCMR1;    //捕获/比较模式寄存器1
	uint32 CCMR2;    //捕获/比较模式寄存器2
	uint32 CCER;     //捕获/比较使能寄存器
	uint32 CNT;      //计数器
	uint32 PSC;      //预分频器
	uint32 ARR;      //自动装载寄存器
	uint32 RCR;      //重复计数寄存器
	uint32 CCR1;     //捕获/比较寄存器1
	uint32 CCR2;     //捕获/比较寄存器2
	uint32 CCR3;     //捕获/比较寄存器3
	uint32 CCR4;     //捕获/比较寄存器4
	uint32 BDTR;     //刹车和死区寄存器
	uint32 DCR;      //DMA控制寄存器
	uint32 DMAR;     //连续模式的DMA地址
}ADVANCED_TIMX_REGS;

typedef struct tagGENERAL_TIMX_REGS{		  //X=2-4
	uint32 CR1;      //控制寄存器1
	uint32 CR2;      //控制寄存器2
	uint32 SMCR;     //从模式控制寄存器
	uint32 DIER;     //DMA/中断使能寄存器
	uint32 SR;       //状态寄存器
	uint32 EGR;      //事件产生寄存器
	uint32 CCMR1;    //捕获/比较模式寄存器1
	uint32 CCMR2;    //捕获/比较模式寄存器2
	uint32 CCER;     //捕获/比较使能寄存器
	uint32 CNT;      //计数器
	uint32 PSC;      //预分频器
	uint32 ARR;      //自动装载寄存器
	uint32 CCR1;     //捕获/比较寄存器1
	uint32 CCR2;     //捕获/比较寄存器2
	uint32 CCR3;     //捕获/比较寄存器3
	uint32 CCR4;     //捕获/比较寄存器4
	uint32 DCR;      //DMA控制寄存器
	uint32 DMAR;     //连续模式的DMA地址
}GENERAL_TIMX_REGS;

#define TIM1 ((volatile ADVANCED_TIMX_REGS *) 0x40012C00) //高级控制定时器1寄存器组首地址
#define TIM2 ((volatile GENERAL_TIMX_REGS *) 0x40000000)  //通用控制定时器2寄存器组首地址
#define TIM3 ((volatile GENERAL_TIMX_REGS *) 0x40000400)  //通用控制定时器3寄存器组首地址
#define TIM4 ((volatile GENERAL_TIMX_REGS *) 0x40000800)  //通用控制定时器4寄存器组首地址

//####################################################################################
//*****ADC REGS******//
//####################################################################################

typedef struct tagADCX_REGS{
	uint32 SR;      //ADC状态寄存器
	uint32 CR1;     //ADC控制寄存器1
	uint32 CR2;     //ADC控制寄存器2
	uint32 SMPR1;   //ADC采样时间寄存器1
	uint32 SMPR2;   //ADC采样时间寄存器2
	uint32 JOFR1;   //ADC注入通道数据偏移寄存器1
	uint32 JOFR2;   //ADC注入通道数据偏移寄存器2
	uint32 JOFR3;   //ADC注入通道数据偏移寄存器3
	uint32 JOFR4;   //ADC注入通道数据偏移寄存器4
	uint32 HTR;     //ADC看门狗高阀值寄存器
	uint32 LTR;     //ADC看门狗低阀值寄存器
	uint32 SQR1;    //ADC规则序列寄存器1
	uint32 SQR2;    //ADC规则序列寄存器2
	uint32 SQR3;    //ADC规则序列寄存器3
	uint32 JSQR;    //ADC注入序列寄存器
	uint32 JDR1;    //ADC 注入数据寄存器1
	uint32 JDR2;    //ADC 注入数据寄存器2
	uint32 JDR3;    //ADC 注入数据寄存器3
	uint32 JDR4;    //ADC 注入数据寄存器4
	uint32 DR;      //ADC规则数据寄存器	
}ADCX_REGS;

#define ADC1 ((volatile ADCX_REGS *) 0x40012400)	//ADC1寄存器组首地址
#define ADC2 ((volatile ADCX_REGS *) 0x40012800)	//ADC2寄存器组首地址


//等等。。。。。。


#endif

     

       如上,然后我们就可以在.c文件里包含这个头文件,并根据技术手册里的各外设的寄存器描述来读写相应的寄存器,完成想要实现的功能。

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

注意:

        可能你在编译过程中会报错,大体意思是说你没有定义某结构体,可我们明明定义了,我想这可能是KEIL的一个BUG(当然也有可能是盗版的缘故~),经过几次猜想验证之后,我发现在typedef struct...这个结构体定义时,在最后的结构体名一定要是你一个字一个字敲进去的,而不是从tagXXX中拷贝而来的,如果是从tagXXX拷贝而来的话就会报上述的错误(真是什么奇怪的事都可能存在~)。

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

     欢迎大家扫描下方二维码关注我的个人微信公众号,一起交流学习,谢谢。

      

     

     

缓存第三篇:redis入门之下载安装和命令行使用

今天上午整理了一下redis的入门必备资料,以备后续使用。到官网看了下稳定版到3.2,测试版到4.0了。但我下载3.2解压发现没有redis-server,一直无法正常用命令行启动。就在GitHub上...
  • zhanglf02
  • zhanglf02
  • 2017年07月08日 11:33
  • 694

今天学的是传说中的c语言灵魂指针。。

今天就让我带大家走进传说中的指针吧。。。
  • zhangke_zhangke
  • zhangke_zhangke
  • 2014年10月24日 22:08
  • 430

带你认识指针——C语言的灵魂(一)

前言 最近复习考研的知识,有机会研究一下C语言的指针,今天就总结一下到底让我们有时候爱的要死,有时候也恨得要死的指针,到底是什么?书里指针那章的序言说到了,不掌握指针就是没有掌握C的精华,word指针...
  • cd18333612683
  • cd18333612683
  • 2016年11月29日 15:22
  • 1062

C++灵魂所在之---多态的前世与今生

优秀是一种习惯               众所周知,在20世纪80年代早期,C++在贝尔实验室诞生了,这是一门面向对象的语言,但它又不是全新的面向对象的语言,它是在传统的语言(C语言)进行面向对...
  • Loving_Forever_
  • Loving_Forever_
  • 2016年06月13日 15:45
  • 1615

【Android图像处理】老照片滤镜(效果)

说到老照片,很多人就会想起儿时的照片。没错,老照片就是这样的,我称之为情怀滤镜。 先说一下Android图像矩阵处理(图片来源  慕课网) 也就是说,每一个矩阵都对应着一个唯一的滤镜(效果...
  • qq_32353771
  • qq_32353771
  • 2016年11月17日 22:42
  • 600

程序的灵魂——算法

软件工程的思想告诉我们,软件包含两部分内容,一部分是计算机可执行的程序和相关的数据,一部分是与程序及数据有关的描述性文档。也即:软件=程序和数据+文档。对于一个毫无开发经验,刚开始学习计算机编程的人而...
  • u011955603
  • u011955603
  • 2014年07月14日 19:56
  • 1254

浅谈MVC之框架说明

为什么使用自己封装的框架 为任何事物的执行都是有目的性的,因为有目的或者说有便利才会去执行事务! 同样的我们封装框架也是对自己有便利才会去封装,现如今世面上优秀成熟的web框架很多,那么我们为什么...
  • zl941107
  • zl941107
  • 2016年09月29日 11:58
  • 106

优秀程序员的 18 大法则

经过多年的积累,我发现,下面这些基本的指导法则,可以帮助我成为一个更加高效的程序员。程序设计法则,与设计和工程的原理密切相关。下面这些编程法则帮助我让我获益匪浅,所以我想分享给大家,希望也能帮助大家更...
  • u011225629
  • u011225629
  • 2015年10月20日 19:48
  • 1757

C++灵魂所在之---继承篇

在C++的学习过程之中,那么继承与多态这两个区别于C语言的特性你一定要了解,如果想要学好C++,那么继承与多态必须要了解清楚,尤其是多态,但是要了解多态首先你又必须了解继承先,不过即使这两者都十分了解...
  • Loving_Forever_
  • Loving_Forever_
  • 2016年06月11日 23:07
  • 2098

做技术需要匠心(转)

做技术是需要匠心的。什么是匠心?我们原本是有匠心的,我们如今还有匠心吗?我们为什么没有匠心了?为什么我们要重拾匠心?如何重拾匠心? 一. 做技术是需要匠心的 中国古时的玉匠,切磋琢磨,用绳与砂...
  • fangxiangmu
  • fangxiangmu
  • 2016年05月19日 21:45
  • 437
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第三篇---STM32灵魂塑造之呱呱坠地
举报原因:
原因补充:

(最多只允许输入30个字)