读芯片手册
主要是读地址,层层递进
- 首先查阅GEC-M4原理图的pdf,找出芯片对应的引脚标号
- 查阅芯片手册,层层递进找到对应的基地址(RCC寄存器和GPIO寄存器)
任务案例
例一
查阅芯片手册和原理图,实现功能:
四个按键对应控制四个灯,按下亮,松开灭
代码如下:
#include "stm32f4xx.h"
#define RCC_BASEADDR 0x40023800 //RCC外设基地址
#define RCC_AHB1ENR *(int *)(RCC_BASEADDR+0x30) //AHB1基地址
#define GPIOA_BASEADDR 0x40020000 //GPIOA外设基地址
#define GPIOA_MODER *(int *)(GPIOA_BASEADDR+0x00) //模式寄存器
#define GPIOA_OTYPER *(int *)(GPIOA_BASEADDR+0x04) //输出寄存器
#define GPIOA_OSPEEDR *(int *)(GPIOA_BASEADDR+0x08) //速度寄存器
#define GPIOA_PUPDR *(int *)(GPIOA_BASEADDR+0x0C) //上下拉寄存器
#define GPIOA_ODR *(int *)(GPIOA_BASEADDR+0x14) //输出数据寄存器
#define GPIOA_IDR *(int *)(GPIOA_BASEADDR+0x10) //输入数据寄存器
#define GPIOE_BASEADDR 0x40021000 //GPIOE外设基地址
#define GPIOE_MODER *(int *)(GPIOE_BASEADDR+0x00) //模式寄存器
#define GPIOE_OTYPER *(int *)(GPIOE_BASEADDR+0x04) //输出寄存器
#define GPIOE_OSPEEDR *(int *)(GPIOE_BASEADDR+0x08) //速度寄存器
#define GPIOE_PUPDR *(int *)(GPIOE_BASEADDR+0x0C) //上下拉寄存器
#define GPIOE_ODR *(int *)(GPIOE_BASEADDR+0x14) //输出数据寄存器
#define GPIOE_IDR *(int *)(GPIOE_BASEADDR+0x10) //输入数据寄存器
#define GPIOF_BASEADDR 0x40021400 //GPIOF外设基地址
#define GPIOF_MODER *(int *)(GPIOF_BASEADDR+0x00) //模式寄存器
#define GPIOF_OTYPER *(int *)(GPIOF_BASEADDR+0x04) //输出寄存器
#define GPIOF_OSPEEDR *(int *)(GPIOF_BASEADDR+0x08) //速度寄存器
#define GPIOF_PUPDR *(int *)(GPIOF_BASEADDR+0x0C) //上下拉寄存器
#define GPIOF_ODR *(int *)(GPIOF_BASEADDR+0x14) //输出数据寄存器
int main(void)
{
/*开启时钟AHB1*/
RCC_AHB1ENR |= (0x1 << 0); //GPIOA
RCC_AHB1ENR |= (0x1 << 4); //GPIOE
RCC_AHB1ENR |= (0x1 << 5); //GPIOF
/*配置输出输入模式*/
//GPIOA
GPIOA_MODER &= ~(0x3<<2*0); //key0
//GPIOF
GPIOF_MODER &= ~(0x3 << 2*8); //beep
GPIOF_MODER |= (0x1 << 2*8);
GPIOF_MODER &= ~(0x3 << 2*9); //led0
GPIOF_MODER |= (0x1 << 2*9);
GPIOF_MODER &= ~(0x3 << 2*10); //led1
GPIOF_MODER |= (0x1 << 2*10);
//GPIOE
GPIOE_MODER &= ~(0x3 << 2*13); //led2
GPIOE_MODER |= (0x1 << 2*13);
GPIOE_MODER &= ~(0x3 << 2*14); //led3
GPIOE_MODER |= (0x1 << 2*14);
GPIOE_MODER &= ~(0x3 << 2*2); //key1
GPIOE_MODER &= ~(0x3 << 2*3); //key2
GPIOE_MODER &= ~(0x3 << 2*4); //key3
/*配置输出模式为推挽输出*/
//GPIOF
GPIOF_OTYPER &= (0x1<<1*8); //beep
GPIOF_OTYPER &= (0x1 << 1*9); //led0
GPIOF_OTYPER &= (0x1 << 1*10); //led1
//GPIOE
GPIOE_OTYPER &= (0x1 << 1*13); //led2
GPIOE_OTYPER &= (0x1 << 1*14); //led3
/*输出速度25M中速*/
//GPIOF
GPIOF_OSPEEDR &= ~(0x3<<2*8); //beep
GPIOF_OSPEEDR |= (0x1<<2*8);
GPIOF_OSPEEDR &= ~(0x3 << 2*9); //led0
GPIOF_OSPEEDR |= (0x1 << 2*9);
GPIOF_OSPEEDR &= ~(0x3 << 2*10); //led1
GPIOF_OSPEEDR |= (0x1 << 2*10);
//GPIOE
GPIOE_OSPEEDR &= ~(0x3 << 2*13); //led2
GPIOE_OSPEEDR |= (0x1 << 2*13);
GPIOE_OSPEEDR &= ~(0x3 << 2*14); //led3
GPIOE_OSPEEDR |= (0x1 << 2*14);
/*设置上下拉模式*/
//GPIOA
GPIOA_PUPDR &= ~(0x3<<2*0); //key0
//GPIOF
GPIOF_PUPDR &= ~(0x3<<2*8); //beep
GPIOF_PUPDR |= (0x1<<2*8);
GPIOF_PUPDR &= ~(0x3 << 2*9); //led0
GPIOF_PUPDR |= (0x1 << 2*9);
GPIOF_PUPDR &= ~(0x3 << 2*10); //led1
GPIOF_PUPDR |= (0x1 << 2*10);
//GPIOE
GPIOE_PUPDR &= ~(0x3 << 2*13); //led2
GPIOE_PUPDR |= (0x1 << 2*13);
GPIOE_PUPDR &= ~(0x3 << 2*14); //led3
GPIOE_PUPDR |= (0x1 << 2*14);
GPIOE_PUPDR &= ~(0x3 << 2*2); //key1
GPIOE_PUPDR &= ~(0x3 << 2*3); //key2
GPIOE_PUPDR &= ~(0x3 << 2*4); //key3
/*高电平*/
GPIOF_ODR &= ~(0x1<<1*8);
GPIOF_ODR |= (0x1 <<1*9);
GPIOF_ODR |= (0x1 <<1*10);
GPIOE_ODR |= (0x1 <<1*13);
GPIOE_ODR |= (0x1 <<1*14);
/*低电平*/
/*GPIOF_ODR &=~ (0x1 <<1*9);
GPIOF_ODR &=~ (0x1 <<1*10);
GPIOE_ODR &=~ (0x1 <<1*13);
GPIOE_ODR &=~ (0x1 <<1*14);*/
while (1)
{
if((GPIOA_IDR &(0x1<<1*0))==0) GPIOF_ODR &=~ (0x1 <<1*9);
else GPIOF_ODR |= (0x1 <<1*9);
if((GPIOE_IDR &(0x1<<1*2))==0) GPIOF_ODR &= ~(0x1 <<1*10);
else GPIOF_ODR |= (0x1 <<1*10);
if((GPIOE_IDR &(0x1<<1*3))==0) GPIOE_ODR &= ~(0x1 <<1*13);
else GPIOE_ODR |= (0x1 <<1*13);
if((GPIOE_IDR &(0x1<<1*4))==0) GPIOE_ODR &= ~(0x1 <<1*14);
else GPIOE_ODR |= (0x1 <<1*14);
daley(100);
}
return 0;
}
例二
实现流水灯等花样显示,并且实现蜂鸣器发声。
代码如下:
#include "stm32f4xx.h"
typedef struct
{
unsigned int MODER;
unsigned int OTYPER;
unsigned int OSPEEDR;
unsigned int PUPDR;
unsigned int IDR;
unsigned int ODR;
} GPIO_Type;
//外设基地址
#define GPIOA_BASEADDR 0x40020000 //GPIOA
#define GPIOE_BASEADDR 0x40021000 //GPIOE
#define GPIOF_BASEADDR 0x40021400 //GPIOF
#define GPIOa ((GPIO_Type *)GPIOA_BASEADDR)
#define GPIOe ((GPIO_Type *)GPIOE_BASEADDR)
#define GPIOf ((GPIO_Type *)GPIOF_BASEADDR)
#define RCC_BASEADDR 0x40023800 //RCC外设基地址
#define RCC_AHB1ENR *(unsigned int *)(RCC_BASEADDR+0x30) //AHB1基地址
void delay_ms(int ms)
{
int i,j;
for(i=0; i<ms; i++)
{
for(j=0; j<10000; j++);
}
}
void config()
{
/*开启时钟AHB1*/
RCC_AHB1ENR |= (0x1 << 0); //GPIOA
RCC_AHB1ENR |= (0x1 << 4); //GPIOE
RCC_AHB1ENR |= (0x1 << 5); //GPIOF
/*配置为输出模式*/
//GPIOF
GPIOf->MODER &= ~(0x3 << 2*8); //beep
GPIOf->MODER |= (0x1 << 2*8);
GPIOf->MODER &= ~(0x3 << 2*9); //led0
GPIOf->MODER |= (0x1 << 2*9);
GPIOf->MODER &= ~(0x3 << 2*10); //led1
GPIOf->MODER |= (0x1 << 2*10);
//GPIOE
GPIOe->MODER &= ~(0x3 << 2*13); //led2
GPIOe->MODER |= (0x1 << 2*13);
GPIOe->MODER &= ~(0x3 << 2*14); //led3
GPIOe->MODER |= (0x1 << 2*14);
/*配置为输入模式*/
GPIOa->MODER &= ~(0x3 << 2*0); //key1
GPIOe->MODER &= ~(0x3 << 2*2); //key2
GPIOe->MODER &= ~(0x3 << 2*3); //key3
GPIOe->MODER &= ~(0x3 << 2*4); //key4
/*配置输出模式为推挽输出*/
//GPIOF
GPIOf->OTYPER &= (0x1 << 1*8); //beep
GPIOf->OTYPER &= (0x1 << 1*9); //led0
GPIOf->OTYPER &= (0x1 << 1*10); //led1
//GPIOE
GPIOe->OTYPER &= (0x1 << 1*13); //led2
GPIOe->OTYPER &= (0x1 << 1*14); //led3
/*输出速度25M中速*/
//GPIOF
GPIOf->OSPEEDR &= ~(0x3 << 2*8); //beep
GPIOf->OSPEEDR |= (0x1 << 2*8);
GPIOf->OSPEEDR &= ~(0x3 << 2*9); //led0
GPIOf->OSPEEDR |= (0x1 << 2*9);
GPIOf->OSPEEDR &= ~(0x3 << 2*10); //led1
GPIOf->OSPEEDR |= (0x1 << 2*10);
//GPIOE
GPIOe->OSPEEDR &= ~(0x3 << 2*13); //led2
GPIOe->OSPEEDR |= (0x1 << 2*13);
GPIOe->OSPEEDR &= ~(0x3 << 2*14); //led3
GPIOe->OSPEEDR |= (0x1 << 2*14);
/*设置上下拉模式为上拉*/
//GPIOF
GPIOf->PUPDR &= ~(0x3 << 2*9); //beep
GPIOf->PUPDR |= (0x1 << 2*9);
GPIOf->PUPDR &= ~(0x3 << 2*9); //led0
GPIOf->PUPDR |= (0x1 << 2*9);
GPIOf->PUPDR &= ~(0x3 << 2*10); //led1
GPIOf->PUPDR |= (0x1 << 2*10);
//GPIOE
GPIOe->PUPDR &= ~(0x3 << 2*13); //led2
GPIOe->PUPDR |= (0x1 << 2*13);
GPIOe->PUPDR &= ~(0x3 << 2*14); //led3
GPIOe->PUPDR |= (0x1 << 2*14);
/*设置上下拉模式为保留*/
GPIOa->PUPDR &= ~(0x3 << 2*0); //key1
GPIOa->PUPDR |= (0x3 << 2*0);
GPIOe->PUPDR &= ~(0x3 << 2*2); //key2
GPIOe->PUPDR |= (0x3 << 2*2);
GPIOe->PUPDR &= ~(0x3 << 2*3); //key3
GPIOe->PUPDR |= (0x3 << 2*3);
GPIOe->PUPDR &= ~(0x3 << 2*4); //key4
GPIOe->PUPDR |= (0x3 << 2*4);
}
int main(void)
{
int a;
config();
while(1)
{
/*高电平*/
GPIOf->ODR |= (0x1 <<1*9);
GPIOf->ODR |= (0x1 <<1*10);
GPIOe->ODR |= (0x1 <<1*13);
GPIOe->ODR |= (0x1 <<1*14);
//key1 蜂鸣器响四下
if(GPIOa->IDR == (GPIOa->IDR & (~(0x1 <<1*0))))
{
for(a=0; a<4; a++)
{
GPIOe->IDR |= (0x1 <<1*4);
GPIOf->ODR |= (0x1 <<1*8);
delay_ms(100);
GPIOf->ODR &=~ (0x1 <<1*8);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
}
}
//key2 亮暗交替闪烁
if(GPIOe->IDR == (GPIOe->IDR& (~(0x1 <<1*2))))
{
//GPIOE_IDR |= (0x1 <<1*2);
for(a=0; a<4; a++)
{
/*低电平*/
GPIOf->ODR &=~ (0x1 <<1*9);
GPIOf->ODR &=~ (0x1 <<1*10);
GPIOe->ODR &=~ (0x1 <<1*13);
GPIOe->ODR &=~ (0x1 <<1*14);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
/*高电平*/
GPIOf->ODR |= (0x1 <<1*9);
GPIOf->ODR |= (0x1 <<1*10);
GPIOe->ODR |= (0x1 <<1*13);
GPIOe->ODR |= (0x1 <<1*14);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
}
}
//key3 流水灯
if(GPIOe->IDR == (GPIOe->IDR& (~(0x1 <<1*3))))
{
//GPIOE_IDR |=(0x1 <<1*3);
/*低电平*/
GPIOf->ODR &=~ (0x1 <<1*9);
delay_ms(100);
GPIOf->ODR &=~ (0x1 <<1*10);
delay_ms(100);
GPIOe->ODR &=~ (0x1 <<1*13);
delay_ms(100);
GPIOe->ODR &=~ (0x1 <<1*14);
delay_ms(100);
/*高电平*/
GPIOf->ODR |= (0x1 <<1*9);
delay_ms(100);
GPIOf->ODR |= (0x1 <<1*10);
delay_ms(100);
GPIOe->ODR |= (0x1 <<1*13);
delay_ms(100);
GPIOe->ODR |= (0x1 <<1*14);
delay_ms(100);
}
//key4 第一、三灯亮,第二、四灯暗,然后交替闪烁
if(GPIOe->IDR == (GPIOe->IDR& (~(0x1 <<1*4))))
{
//GPIOE_IDR |= (0x1 <<1*2);
for(a=0; a<4; a++)
{
GPIOf->ODR |= (0x1 <<1*9);
GPIOf->ODR &=~ (0x1 <<1*10);
GPIOe->ODR |= (0x1 <<1*13);
GPIOe->ODR &=~ (0x1 <<1*14);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
GPIOf->ODR &=~ (0x1 <<1*9);
GPIOf->ODR |= (0x1 <<1*10);
GPIOe->ODR &=~ (0x1 <<1*13);
GPIOe->ODR |= (0x1 <<1*14);
delay_ms(100);
delay_ms(100);
delay_ms(100);
delay_ms(100);
}
}
}
return 0;
}