1.准备
复制第07节完成的template_CSG文件夹,重命名为REG_LED,
2.编写程序
程序目的:点亮PB0对应的灯
stm32中,不能像51单片机一样,写成PB=0xFFFE;
stm32输出由端口输出寄存器控制,需要先配置端口输出寄存器GPIO_ODR,使PB0=0
配置端口输出寄存器GPIOx_ODR
在F10x参考手册中发现,GPIO_ODR高16位为0,低16位每一位对应一个端口,
PB0对应的是GPIO_ODR第0位
查找端口B基地址为0X4001 0C00,又GPIO_ODR的偏移地址为0Ch,
//配置IO口为输出
*(unsigned int *)0x40010C00 &=~(1<<0);
配置端口配置低寄存器GPIOx_CRL
配置端口配置低寄存器GPIOx_CRL,32位共配置低8位I/O口,每4位对应1个,
PB0对应3210四位,配置PB0为通用推挽输出模式,输出模式,最大速度10MHz,配置为0001
//配置寄存器清零
*(unsigned int *)0x40010C00 &=~((0x0f)<<(4*0));
//配置IO口为输出
*(unsigned int *)0x40010C00 |=((1)<<(4*0));
//上述(~(3<<2*1))中的(1)即为组编号,如清零第 3 组 bit6、 bit7 此处应为 3
//括号中的(2)为每组的位数,每组有 2 个二进制位;若分成 4 个一组,此处即为 4
//括号中的(3)是组内所有位都为 1 时的值;若分成 4 个一组,此处即为二进制数“1111 b”
**
配置APB2 外设时钟使能寄存器RCC_APB2ENR
由F10x参考手册第2章,GPIOB属于APB2总线外接设备,需要配置APB2 外设时钟使能寄存器(RCC_APB2ENR)
要是端口B正常工作,需要使端口B时钟使能,第3位置1
RCC寄存器基地址位0x4002 1000,偏移地址为0x18,
//打开GPIOB端口时钟
*(unsigned int *)0x40021018 |= (1<<3);
编写程序
在REG_LED文件夹中打开程序
stm32f10x.h中编写为:
//用来存放STM32寄存器映射的代码
main.c中编写为:
编译后报错,错误为main.c(28): error: #137: expression must be a modifiable lvalue
0x40010C0C 在编译器认为成立即数,
改为
#include"stm32f10x.h"
int main(void)
{
//打开GPIOB端口时钟
*(unsigned int *)0x40021018 |= (1<<3);
//配置IO口为输出
*(unsigned int *)0x40010C00 |= ((1)<<(4*0));
//配置ODR寄存器
*(unsigned int *)0x40010C0C &= ~(1<<0);
}
void SystemInit(void)
{
//函数体为空,目的为骗过编译器不报错
}
3.烧写程序
设置好仿真器部分,点击编译,没有错误后点击下载即可
编译按钮
下载按钮
4.点亮3个led灯
时钟使能
RCC_APB2基地址: 0x4002 1000,偏移地址: 0x18 ,1<<3,使端口B**时钟使能**
端口B基地址: 0X4001 0C00,
端口配置
PB0、
(unsigned int )0x40010C00 |= ((1)<<(40));
PB1
(unsigned int )0x40010C00 |= ((1)<<(41));
PB5
(unsigned int )0x40010C00 |= ((1)<<(45));
端口输出
(unsigned int )0x40010C0C &= ~(1<<0);
(unsigned int )0x40010C0C &= ~(1<<1);
(unsigned int *)0x40010C0C &= ~(1<<5);
#include"stm32f10x.h"
int main(void)
{
//打开GPIOB端口时钟
*(unsigned int *)0x40021018 |= (1<<3);
//配置IO口为输出
*(unsigned int *)0x40010C00 |= ((1)<<(4*0));
*(unsigned int *)0x40010C00 |= ((1)<<(4*1));
*(unsigned int *)0x40010C00 |= ((1)<<(4*5));
//配置ODR寄存器
*(unsigned int *)0x40010C0C &= ~(1<<0);
*(unsigned int *)0x40010C0C &= ~(1<<1);
*(unsigned int *)0x40010C0C &= ~(1<<5);
}
void SystemInit(void)
{
//函数体为空,目的为骗过编译器不报错
}
C语言小知识
置位、清零
置位 |= , 清零&=~
举例:如配置端口输出寄存器GPIO_ODR,使PB0=0
直接写(unsigned int )0x40010C0C = 0;会改变ODR寄存器其他位原来数值,
stm32晶振频率
stm32f10x.h头文件中会将晶振配置为72MHZ,但若头文件未配置晶振频率,则会使用stm32内部晶振频率,HSI=8MHz
void main(void)含义
第一个void 表示main函数的返回值为空,
(void)表示main函数的形参为空
怎么注释某一段代码
方法1:
选中代码,点击comment selection,即可将该段注释
方法2:
在该段开头和结尾分别添加#if 0和#endif,则该段不会被编译
51单片机程序示范
假设1个led灯,一端接5V,1端接51单片机P0^0,将其点亮
#include <reg52.h>
sbit LED=P0^0;
void main(void )
{
P0=0xFE;//总线操作
LED=0;//位操作
}
关闭keil5C语言语法检查
点击Edit/configuration。取消勾选Dynamic Syntax Checking的Enable即可