?STM32 的 GPIO 外设是挂在 APB2 总线上 由参考手册(28)及原理图知,点亮led灯先使GPIOB时钟使能
查看参考手册 APB2 GPIOB的时钟使能寄存器RCC_ APB2ENR?知 将位3置1 开启端口B时钟
APB2 GPIOB基地址0X40010C00? 加上偏移地址0x18? ? ?
即将地址0X40010C18? ? ?位3置为1开启端口B时钟
*(unsigned int *)0X40010C18 | =? (1<<3);//GPIOB的时钟使能? 具体语法说明详细可看野火stm32指南针随记1
RGBLED 三色灯分别由PB0 PB1 PB5控制(均在端口配置低寄存器CRL) 点亮哪个LED就将哪位配置相应的I/O端口
将MODE 配置位0 1? ? ?CNF配置为 0 0表示通用推挽输出,输出速率最大 10MHz 即0001
同理GPIOB基地址0X40010C00? 加上偏移地址0x00? 为端口配置低寄存器地址
即将地址0X40010C18 4~0置为0001
*(unsigned int *)0X40010C00 |=((1)<<(4*0));//PB0,绿灯
*(unsigned int *)0X40010C00 |=((1)<<(4*1));//PB1,蓝灯
*(unsigned int *)0X40010C00 |=((1)<<(4*5));//PB5,红灯
由上电路图知,IO口输出低电平LED点亮
?STM32 的 GPIOB 输出数据寄存器(ODR)相对于端口的偏移地址为 0x0C
GPIOB基地址0X40010C00? 加上偏移地址0x0C? 为输出数据寄存器地址
即将0X40010C0C 位0 位1 位5 分别?清零 点亮绿 蓝 红灯
*(unsigned int *)0X40010C0C &=~(1<<0);//控制ODR点亮绿灯
*(unsigned int *)0X40010C0C &=~(1<<1);//控制ODR点亮蓝灯
*(unsigned int *)0X40010C0C &=~(1<<5);//控制ODR点亮红灯
综上可有如下代码.
1.分别点亮三个led
#include "stm32f10x.h"
int main (void)
{
while(1)
{
//下述代码复制一处即可点亮对应led 若全部运行则为白灯
//点亮绿灯
*(unsigned int *)0X40021018 |=((1)<<(3));//GPIOB时钟
*(unsigned int *)0X40010C00 |=((1)<<(4*0));//配置GPIO0为输出
*(unsigned int *)0X40010C0C &=~(1<<0);//PB0 ODR 输出数据为0 亮绿灯
Delay(500);
//点亮蓝灯
*(unsigned int *)0X40021018 |=((1)<<(3));//GPIOB时钟
*(unsigned int *)0X40010C00 |=((1)<<(4*1));//配置IO为输出
*(unsigned int *)0X40010C0C &=~(1<<1);//PB1 ODR 输出数据为0 亮蓝灯
//点亮红灯
*(unsigned int *)0X40021018 |=((1)<<(3));//GPIOB时钟
*(unsigned int *)0X40010C00 |=((1)<<(4*5));//配置IO为输出
*(unsigned int *)0X40010C0C &=~(1<<5);//PB5 ODR 输出数据为0 亮红灯
}
}
void SystemInit(void)
{
//骗过编译器
}
2.通过延时函数实现闪烁灯
注:C 语言规定:函数在被调用之前,必须先被定义或声明。意思就是说:在一个文件中,一个函数应该先定义,然后才能被调用,也就是调用函数应位于被调用函数的下方。
因为一般main函数放在开头,所以其他函数定义之前,开辟一块区域,叫做函数声明区,用来把被调用的函数声明一下
故在使用延时函数之前,需要先进行函数声明
实现绿蓝红闪烁
#include "stm32f10x.h"
void Delay(unsigned int count);//函数声明
int main (void)
{
while(1)
{
//*(unsigned int*)0x40010c0 &=~((0x0f)<(4*0)):可用该操作复位CRL寄存器对应位(因为使
//用清零 置位操作不改变原值)
//点亮绿灯
*(unsigned int *)0X40021018 |=((1)<<(3));//GPIOB时钟
*(unsigned int *)0X40010C00 |=((1)<<(4*0));//配置GPIO0为输出
*(unsigned int *)0X40010C0C &=~(1<<0);//PB0 ODR 输出数据为0 亮绿灯
Delay(500);
//点亮蓝灯
*(unsigned int *)0X40010C0C |=(1<<0);//PB0 ODR 输出数据为1 灭绿灯
*(unsigned int *)0X40021018 |=((1)<<(3));//GPIOB时钟
*(unsigned int *)0X40010C00 |=((1)<<(4*1));//配置IO为输出
*(unsigned int *)0X40010C0C &=~(1<<1);//PB1 ODR 输出数据为0 亮蓝灯
Delay(500);
//点亮红灯
*(unsigned int *)0X40010C0C |=(1<<1);//PB1 ODR 输出数据为1 灭蓝灯
*(unsigned int *)0X40021018 |=((1)<<(3));//GPIOB时钟
*(unsigned int *)0X40010C00 |=((1)<<(4*5));//配置IO为输出
*(unsigned int *)0X40010C0C &=~(1<<5);//PB5 ODR 输出数据为0 亮红灯
Delay(500);
*(unsigned int *)0X40010C0C |=(1<<5);///PB5 ODR 输出数据为0 灭红灯
}
}
void SystemInit(void)
{
//骗过编译器
}
void Delay(unsigned int count)//延时函数
{
unsigned int i;
for(; count!=0; count--)
{
i = 5000;
while(i--);
}
}
程序?采用非精确延时, 由左侧寄存器sec值相减可知每次延时时间约为1s