day04:点亮一个LED

=========== 以下步骤比较繁琐,请参考 http://www.cnblogs.com/josephcnblog/articles/8846801.html

(1)查看STM32原理图:比如要点亮D4这个LED,它的阳极(+)接在3V3的高电平,所以要点亮这个LED,就要让它的阴极(-)输出低电平(0V)。

PC2表示输出端口号。D4表示LED灯别名。

(2)查看STM32F10X中文手册

看GPIO寄存器:

因为LED端口号是PC2,表示第三个端口(端口从0开始)。高16位保留(用户不能操作),第十六位可设置。

先来理解一个位运算的知识:

所以,要将第三位清零,只需要把它的地址指针的值进行 &= ~ 位运算即可。

而单片机中用的是内存地址,而C中用的是指针,这两者是对应的。

但是只有地址偏移,没有真正的内存地址,真正地址 = 起始地址 + 地址偏移,而寄存器是有特殊功能的内存单元,给单元分配内存地址就是映射过程,

所以查找“存储器映射”资料:

查看第三个端口,即C端口,它的起始地址是:0X4001 1000,加上地址偏移 0Ch,即C,结果是:0X4001 100C

所以,配置ODR寄存器是: *(unsigned int *)0X4001100C &= ~(1<<2),下面解释这句代码:看下面的解释就懂

1 ============================================== 编译代码,烧录到单片机

#include "stm32f10x.h"

int main(void)
{
	/* 配置ODR寄存器 */
	*(unsigned int *)0X4001100C &= ~(1<<2);
	while(1);
}

点这个图片,将文件输出成 .hex 文件,这个格式文件是可以通过串口烧录到单片机中的

重新编译,点下面的图标:烧录到单片机

打开mcuisp.exe串口程序下载工具:

点击“Build”生成 .hex 文件,报错:缺少。。。。。。。。。.axf 文件,这是因为没有在开发环境中添加GPIO的原因

(参考:https://blog.csdn.net/u011976086/article/details/54342447)

 

勾上:

 

重新“Build”,没有错误了,也生成了 .hex 文件

用USB连接开发板和电脑,点击Load,报错:

 这是因为没有仿真器的原因,但是我没有使用到仿真器(可以直接在Keil中点击Build就能在单片机上看到效果),所以不管它。

用mcuisp.exe串口程序下载工具来讲程序烧录到单片机

 

程序烧录进去了,但是LED灯不亮。(红灯是电源灯,D4蓝灯才是要点亮的灯)

原因是:代码写的不对,省略了两个步骤。

步骤一:开启时钟:因为STM32为了节约消耗,故上电时候外设时钟默认不开启。故我们需要开始GPIO的时钟。

步骤二:设置GPIO输出模式:stm32F103提供了4种输出模式和3种输出速度: 一般使用推挽模式
- 通用输出推挽
- 通用输出开漏
- 复用输出推挽:串口输出
- 复用输出开漏:IIC

打开STM32F103中文开发手册:找RCC时钟控制寄存器(GPIO挂在到APB2总线上),因为D4的LED是PC端口,所以这里找 IOPC端口

将位4置1,其他位不管,所以使用 |= 运算符,而它的真实地址是 = 起始地址 + 地址偏移

起始地址:0X40021000

地址偏移:0X18

所以,真实地址 = 0X40021018,将其强制转换成C中的指针并置1就是:

*(unsigned int *)0X40021018 |= ( 1<<4 );

设置输出模式:

 

 

两位一组,将其配置成0001,即0X01,即将1左移 8 位即可,因为2位一组,偏移地址为0X00,没有偏移,所以真实地址 = 起始地址 = 0X40011000

强制转换之后是:

*(unsigned int *)0X40011000 |= ( 1<<(4*2) );

经过三个步骤:

1.开启时钟

2.设置GPIO输出模式

3.输出低电平

代码如下:

#include "stm32f10x.h"

int main(void)
{
	/* 配置RCC寄存器,使能GPIO口的时钟 */
	*(unsigned int *)0X40021018 |= ( 1<<4 );
	
	/* 配置CRL寄存器,配置为推挽输出 */
	*(unsigned int *)0X40011000 |= ( 1<<(4*2) );
	
	/* 配置ODR寄存器 */
	*(unsigned int *)0X4001100C &= ~( 1<<2 );
	while(1);
}

重新烧录到单片机中,发现D4的那个LED灯被点亮了!

 

简化代码:

#include "stm32f10x.h"

#define GPIO_RCC *(unsigned int *)0X40021018
#define GPIO_CRL *(unsigned int *)0X40011000
#define GPIO_ODR *(unsigned int *)0X4001100C
	
void soft_delay( unsigned int count )
{
	for(; count!=0; count--);
}

int main(void)
{
	/* 配置RCC寄存器,使能GPIO口的时钟 */
	GPIO_RCC |= ( 1<<4 );
	
	/* 配置CRL寄存器,配置为推挽输出 */
	GPIO_CRL |= ( 1<<(4*2) );
	
	/* 配置ODR寄存器 */
	GPIO_ODR &= ~( 1<<2 );

	while(1);
}

 

posted @ 2018-04-15 01:10  半生戎马,共话桑麻、  阅读(269)  评论(0)    收藏  举报
levels of contents