第三篇---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拷贝而来的话就会报上述的错误(真是什么奇怪的事都可能存在~)。

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

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

      

     

     

相关文章推荐

CC254X片上flash读写解析

如果在开发中,希望个别数据掉电不丢失,那么有几种方法可以考虑,一种是通过I2C或者SPI总线外接存储,比如E2PROM或FLASH,如果数据不大,第二种方便的方法就是操作片上flash了,要想操作片上...

第二篇---血肉之躯STM32

又迎来了周末,这个周是单周,只休一天,下午睡了一会儿,本来昏昏沉沉的状态好多了,那就开始干活吧,第一篇学习了CM3的架构,到此还只是理论,那么这第二篇就算正式进入实战了,因为我们开始接触真实的CM3架...

C++学习重要笔记之呱呱坠地

main函数作为接口函数的函数头,编译器都是从这里开始进入执行,有两种类型:分别是返回类型和非返回类型,(int main()和void main()).    我们一般都使用 int main()...

win32汇编 屏幕截图保存BMP 学习笔记<第三篇>之odbg调试

我们来回顾下raiky code 根据帖子里的讨论错误的疑点在于 1. 对每个像素所占字节的估算可能有误 wBitCount;位图中每个像素所占字节数 简单的赋值4 2. 涉及到后面的调色板的...
  • ppluer
  • ppluer
  • 2016年05月12日 12:52
  • 631

STM32 中JTAG 引脚作为普通IO口设置方法

第一次画STM32 的PCB ,因为采用了SWD 调试,认为JTAG的引脚PB3,PB4,没
  • iccome
  • iccome
  • 2014年06月21日 18:10
  • 15472

stm32 RTC实时时钟[操作寄存器+库函数]

"RTC"是Real Time Clock 的简称,意为实时时钟。stm32提供了一个秒中断源和一个闹钟中断源。   RTC的技术器是一个32位的计数器,使用32.768khz的外部晶振。   ...

STM32的CAN总线过滤器的配置

stm32的can总线的配置如下:       CAN_InitStructure.CAN_TTCM=DISABLE;//禁止时间触发通信模式       CAN_InitStructure....

STM32中GPIO的8种工作模式!

1、GPIO_Mode_AIN                 模拟输入 2、GPIO_Mode_IN_FLOATING 浮空输入 3、GPIO_Mode_IPD                下拉...
  • kevinhg
  • kevinhg
  • 2013年12月22日 22:54
  • 51445

STM32F030_USART详细配置说明

STM32F030_USART详细配置说明串口是我们在编程时最经常用的问题,通常用它来发送和接收数据,同时它还有另外一个功能——检测程序是否正确,stm32f030系类单片机自然而然少不了串口,本文主...

STM32Cubemx下实现通用定时器微秒级延时

因为STM32 HAL库中仅有对HAl_Delay()毫秒级的延时,为实现精确的微秒级延时,就不得不修改Systick,但由于HAL库内部使用其作为超时判断等操作,对其修改会发生不可预期的错误,不建议...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第三篇---STM32灵魂塑造之呱呱坠地
举报原因:
原因补充:

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