1.准备

image.png
复制第07节完成的template_CSG文件夹,重命名为REG_LED,

2.编写程序

image.png
程序目的:点亮PB0对应的灯
stm32中,不能像51单片机一样,写成PB=0xFFFE;
stm32输出由端口输出寄存器控制,需要先配置端口输出寄存器GPIO_ODR,使PB0=0

配置端口输出寄存器GPIOx_ODR

image.png
在F10x参考手册中发现,GPIO_ODR高16位为0,低16位每一位对应一个端口,
PB0对应的是GPIO_ODR第0位
image.png
查找端口B基地址为0X4001 0C00,又GPIO_ODR的偏移地址为0Ch,

  1. //配置IO口为输出
  2. *(unsigned int *)0x40010C00 &=~(1<<0);

配置端口配置低寄存器GPIOx_CRL

image.png
配置端口配置低寄存器GPIOx_CRL,32位共配置低8位I/O口,每4位对应1个,
PB0对应3210四位,配置PB0为通用推挽输出模式,输出模式,最大速度10MHz,配置为0001

  1. //配置寄存器清零
  2. *(unsigned int *)0x40010C00 &=~((0x0f)<<(4*0));
  3. //配置IO口为输出
  4. *(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

image.png
由F10x参考手册第2章,GPIOB属于APB2总线外接设备,需要配置APB2 外设时钟使能寄存器(RCC_APB2ENR)
image.png
image.png
要是端口B正常工作,需要使端口B时钟使能,第3位置1
image.png
image.png
RCC寄存器基地址位0x4002 1000,偏移地址为0x18,

  1. //打开GPIOB端口时钟
  2. *(unsigned int *)0x40021018 |= (1<<3);

编写程序

在REG_LED文件夹中打开程序

stm32f10x.h中编写为:

  1. //用来存放STM32寄存器映射的代码

main.c中编写为:
image.png
编译后报错,错误为main.c(28): error: #137: expression must be a modifiable lvalue
0x40010C0C 在编译器认为成立即数,
改为

  1. #include"stm32f10x.h"
  2. int main(void)
  3. {
  4. //打开GPIOB端口时钟
  5. *(unsigned int *)0x40021018 |= (1<<3);
  6. //配置IO口为输出
  7. *(unsigned int *)0x40010C00 |= ((1)<<(4*0));
  8. //配置ODR寄存器
  9. *(unsigned int *)0x40010C0C &= ~(1<<0);
  10. }
  11. void SystemInit(void)
  12. {
  13. //函数体为空,目的为骗过编译器不报错
  14. }

3.烧写程序

设置好仿真器部分,点击编译,没有错误后点击下载即可
image.png
编译按钮
image.png
下载按钮

4.点亮3个led灯

时钟使能
RCC_APB2基地址: 0x4002 1000,偏移地址: 0x18 ,1<<3,使端口B**时钟使能**
image.png
端口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);

  1. #include"stm32f10x.h"
  2. int main(void)
  3. {
  4. //打开GPIOB端口时钟
  5. *(unsigned int *)0x40021018 |= (1<<3);
  6. //配置IO口为输出
  7. *(unsigned int *)0x40010C00 |= ((1)<<(4*0));
  8. *(unsigned int *)0x40010C00 |= ((1)<<(4*1));
  9. *(unsigned int *)0x40010C00 |= ((1)<<(4*5));
  10. //配置ODR寄存器
  11. *(unsigned int *)0x40010C0C &= ~(1<<0);
  12. *(unsigned int *)0x40010C0C &= ~(1<<1);
  13. *(unsigned int *)0x40010C0C &= ~(1<<5);
  14. }
  15. void SystemInit(void)
  16. {
  17. //函数体为空,目的为骗过编译器不报错
  18. }

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:

image.png
选中代码,点击comment selection,即可将该段注释

方法2:

image.png
在该段开头和结尾分别添加#if 0和#endif,则该段不会被编译

51单片机程序示范

image.png
假设1个led灯,一端接5V,1端接51单片机P0^0,将其点亮

  1. #include <reg52.h>
  2. sbit LED=P0^0;
  3. void main(void )
  4. {
  5. P0=0xFE;//总线操作
  6. LED=0;//位操作
  7. }

关闭keil5C语言语法检查

image.png
点击Edit/configuration。取消勾选Dynamic Syntax Checking的Enable即可
image.png