原理学习
一.管脚的规划
eg:对于71管脚 有很多种工作模式:
PA12:可以作为普通的GPIO使用,也叫P212功能
USART1:也可以作为串口的RST管脚,即:使用请求发送的管脚
USBDP:也可以做USB接口来用
CAN_TX:
T1M1:也可以做以太网的timer来使用
但是一个管脚只能工作在一种模式!
要么做GPIO口用,要么做串口用。
二.LED亮灭的按键分析
【电路图】
K3按下,默认接地,是低电平;
K3不按,上面有个上拉电阻,拉成高电平。
/#那么怎么知道按键有没有按下?#/用CPU 判断灯的亮灭,见第二点。
1.CPU控制灯亮灭:对于CPU来说是输出一个电平到外部,以控制灯的亮灭。
第一步:配置GPIO为 输出模式
第二步:cpu->1->外部:灯亮
cpu->0->外部:灯灭
2.CPU判断灯亮灭:对于CPU来说,是读外面这个送进来的电平,来判断灯是亮还是不亮。
第一步:配置GPIO为 输入模式
第二步:外部->1->cpu读 =1:判断为灯亮
外部->0->cpu读=0 :判断为灯灭
三.控制GPIO的寄存器 (32位)
1.GPIO组简介:
GPIO组(A...E):每组端口有16个不同的管脚(0-15号), 对于GPIOA和GPIOB,他们都有互相不相干的一寄存器。如:控制GPIOA 的寄存器为GPIOA_CRL,GPIOA_CRH等..,控制GPIOB的寄存器为GPIOB_CRH,GPIOB_CRL等..
2.你想配置成哪种模式?就去配置它的寄存器。
如:要实现71管脚的5种模式,至少要3个位(bit)存放
2^1(位)=2种 0/1(最多两种模式)
2^2(位)=4种 00/01/10/11(最多四种模式)
2^3(位)=8种 000/001/010/……/111(最多八种模式)
即:1个管脚要3个位,16个端口要 16X3=48位 (bit) (1bit=8字节)(1bit=1位)
stm32的一个寄存器只有32bit,小于48bit,位不够,所以至少要两个寄存器控制。如GPIOx(x=A..E)就需要 GPIOx_CRH高位寄存器、GPIOA_CRL低位寄存器 ..等寄存器控制。
3.控制GPIO组的端口寄存器分类:(7个)
(1)配置寄存器(低寄存器GPIOx_CRL,高寄存器GPIOx_CHL) :选定GPIO的特定功能,最基本的选择作为输入还是输出端口。
(2)数据寄存器(输入寄存器GPIOx_IDR,输出寄存器GPIOx_ODR):保存GPIO的输入或将要输出的电平。
(3)位控制寄存器(GPIOx_BSSR设置/清除寄存器,GPIOx_BRR清除寄存器):设置某引脚的数据为1或0,控制输出电平。
(4)锁定寄存器(GPIOx_LCKR):设置锁定引脚后,不能更改配置。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
***************详细说明*********************:
(1)端口配置高寄存器:CRH管理8-15管脚。一个管脚用四个位。
CNF8(2位)---配置 MODE8(2位)--模式
端口配置低寄存器:CRL管理0-7管脚,一个管脚用四个位。
-----------------------------------------------------------------------------------------------------------------------
实战点灯:寄存器点灯/库点灯(常用)
【电路图】
【具体步骤】
.
------------------------------
一.用库点灯
1.准备好要用到的库,明确好要编写的.c文件和.h文件:
(1)准备好要用到以下库:
STRAT UP : ← startup_stm32f10x_hd.c (启动文件)
CMISS: : ← core_cm3.c (C3核通用文件) + system_stm32f10x.c (设置系统时钟)
FWLIB : ← stm32f10x_rcc.c + stm32f10x_gpio.c (要用到时钟和通用I/O口两个片上外设)
(2)确定用户要编写的文件 :
USER : ← main. c(主函数,控制灯亮灭)+ stm32f10x_it.c(中断函数) + led.c (灯的配置) + led.h(灯的配置头文件)
2.配置工程环境:
进入stm32f10x_conf.h固件配置头文件,使片上外设RCC和GPIO生效,方法:去掉注释
3.编写用户文件(先配置灯,再操作灯)
led.c
/**************************************************************************** * Copyright: (C)2018 武汉凌云嵌入式实验室 www.emblinux.com * Description: 在奋斗STM32 V5开发板上调通过; *LED1-PB5 *LED2-PD6 *LED3-PD3 *hangeLog:https://blog.csdn.net/luoyir1997 *版本号 日期 作者 说明 * V1.0.0 2018.4.21 LUOYIRAN 配置灯的模式 ****************************************************************************/ #include "stm32f10x.h" #include "led.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #define DELAY_TIME 0x3FFFFF /*函数名:LED_GPIO_Config *描述:配置LED用到的I/O口 *输入:无 *输出:无 */ void LED_GPIO_Config(void) { /*定义一个GPIO_*_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启外设时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); /*选择要控制的GPIOB和GPIOD引脚*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; /*设置输出模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; /*设置引脚速度为50MHZ*/ GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; /*调用库函数,初始化GPIOB和GPIOD*/ GPIO_Init(GPIOB,&GPIO_InitStructure); /*关闭所有LED灯*/ GPIO_SetBits(GPIOB,GPIO_Pin_5); } /****************************************************************************************/ /*在这个文件中定义了一个函数LED_GPIO_Config(),在这个函数里,实现了为点亮LED的配置*/
led.h
#ifndef __LED_H #define __LED_H #include "stm32f10x.h" /*定义0-ON 1-OFF*/ #define ON 0 #define OFF 1 void LED_GPIO_Config(void); #endif /*__LED_H*/
main.c
/**************************************************************************** *Copyright: (C)2018 武汉凌云嵌入式实验室 www.emblinux.com *Author:luoyiran QQ: 969303624 *Description: 本例在奋斗STM32 V5开发板上调通过; *LED1-PB5 LED2-PD6 LED3-PD3 *文件名:main.c *描述:点亮LED5 *hangeLog:https://blog.csdn.net/luoyir1997 *版本号 日期 作者 说明 * V1.0.0 2018.4.21 LUOYIRAN 配置灯的模式 ****************************************************************************/ #include "stm32f10x.h" #include "led.h" void Delay(u32 nCount); int main (void) { LED_GPIO_Config(); GPIO_SetBits(GPIOB, GPIO_Pin_5); //亮 Delay(0x0FFFFEF); } void Delay(u32 nCount)//简单的延时函数 { for( ; nCount != 0; nCount--); }
4.编译、下载,因为用的盗版JLINK,跳出东西就点否,就好了。
至此,我们就把LED5点亮啦!
2.寄存器点灯
【要点分析】
0X40001 0C00是起始地址,无符号int 类型,定义用 unsigned int。从这个地址开始取值,取32位,32/8=4个字节
reg =0x4001 0c00 这俩类型一样。但是*reg 是个指针。所以要强制类型转换。
reg 寄存器是 unsigned int*类型的 -->强制转化成:
=
【代码编写】 3步
一.设置初始地址LED5的地址是:0X4001 0C010
reg=0X4001 0C010
这是个整数类型的无符号数 应该用unsigned int
*reg 是指针。要使用强制定义将指针类型转化。
为了防止软、硬件改变寄存器设置,所以要在定义前加volatile
编译器很聪明
假如一开始设置了reg=30;
if reg==30
{
};
后面if以后的PD操作就会被省略,从而寄存器设置被软件改变
因此正确的写法是:
volatile unsigned int* reg(ungined int*)=0x4001 0c10---------------------------------------------------------
位操作方法总结:
要1,或1
要0,取反与1
或01 0 01 1
与01 0 01 1 1-----------------------------------------------------------------------------------------------------
二。设置模式
GPIOX_CRL低配置寄存器
地址偏移0x00
【31:0】【CF7+MOD7:CF0+MODE0】
【3:2】 【1:0】
CF0 bit MODE0 bit
现在我们要求工作模式在:推挽输出,50MHZ,得设置CRL寄存器的CNF和MODE位值,
即:要求将GPIOX_CRL中的数据位设置成:
MODE5的位数据【21:20】=11
CNF5 的位数据【23:20】=00
A)MODE5【21:20】=11
11=0x3
将3左移20位:
0000 0000 0000 0000 00/00/ 0000 0000 0000 0000 0011 (32位)
0000 0000 0000 0000 00/11/ 0000 0000 0000 0000 0000
则20和21位为1,原地址 *reg or 1=1
其他数据位为0,原地址 *reg or 0=不变
∴代码为。
*reg|=11<<20;
------------------------------------------------------------------
B)CNF5【23:22】=00
11=0X3
将11左移22位:0000 0000 0000 0000 /00/00 0000 0000 0000 0000 0011 (32位)
0000 0000 0000 0000 /11/00 0000 0000 0000 0000 0000 (移动后)
~
取反 1111 1111 1111 1111 /00/11 1111 1111 1111 1111 1111
则22和23位为0,原地址*reg & 0 =0
其他数据位为1,原地址*reg & 1 =不变
∴代码为。
*reg &=~(0x03<<22);
----------------------------------------------------------
三。输出高电平
方法一:
ODR端口输出寄存器
地址偏移0X08
【16:31】【位保留】
【15:0】 【ODR15:ODR0】 ODR(out )输出位
输出电平,如点LED5,
设置ODR5=1 输出一个高电平
设置ODR5=0 输出一个低电平
--------------------------------------------------------
方法二:
(GPIOx_BSRR)(x=A..E)端口设置/清除寄存器
地址偏移0X10
【31:16】【BR15:BR0】 BRY (bit reset)清除位 写1清0 BRY=1引脚输出低电平
【0:15】 【BS15:BS0】 BSY (bit set)设置位 写1置1 BSY=1引脚输出高电平
·注意:这两个位写0都是无效的.
如点/灭LED5,需要设置GPIOB5的BSRR位来输出电平:
BS5=1 输出一个高电平
BR5=1 输出一个低电平
现在我们要灯亮,得设置BSRR寄存器的BSY位值
BS5bit
【5】=1
∴代码为。
volatile unsigned int *reg=(unsinged int*)0x4001 0c10;
*regI1<<5;
现在我们要灯灭,得设置BSRR寄存器的BRY位值
BR5bit
【21】=1
∴代码为。
volatile unsigned int*reg=(unsinged int*)0x4001 0c10;
*regI1<<21;
----------------------------------------------------------------