keil实战——新建工程模板
新建项目的时候发现没有32的库,还需要自己添加一下,去官网下载,网址:MDK5 Software Packs
野火视频用的是F1
在网址里找到keil这个标题,往下翻
下载即可
下载完以后双击安装
装了MDK会自动识别,直接点击NEXT,装完以后点击finish
我是装完才截的图,会有警告,没装过的不会有,忽略警告就好
新建步骤如图,视频里讲的很清楚,就不细说了
下图直接关闭即可
添加启动文件,地址如下
A盘(资料盘)\3-STM32官方资料\STM32F103官方固件库与手册(标准库)\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm
把startup_stm32f10x_hd.s复制到工程目录下
复制以后在keil中双击Source Group1,添加此文件到工程里
在目录里新建txt文件,把名字改为main.c ,以同样的步骤把main添加进工程里,别忘了添加.h文件
我txt文件无论怎么改名都无法转换成.c文件
解决办法:
这是我在csdn找的http://t.csdn.cn/0DJQy
1、首先你要有C/C++软件,如DEV-C(下载地址如下Dev-C++ download | SourceForge.net)
2、如果你是WIN10系统。首先打开“此电脑”,依次点“查看”-“选项”-“查看”,将“隐藏已知文件类型的扩展名”前面的勾去掉,再确定,让系统显示完整的文件全名。然后.c后缀就能直接改成C文件。
双击选项
去掉选项以后再进行重命名的操作就可以了
新建项目,编译
此时直接编译的话,会出现如下错误:
“ Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f429_439xx.o)”
错误提示 SystemInit引用但没有定义。
图 2 汇编文件
由图汇编文件可知,运行的时候会先运行SystemInit,初始化系统时钟以后在调用面函数
在main函数外面做一个空实现,即可解决报错
这块我从一开始就出现了意想不到的问题,
然后就是我明明输的和老师一样吧,SystemInit报错no previous prototype for function systeminit
解决办法:
鼠标右键点击Target 1,选择Options for Group‘Source Group 1...’
将 6选成5即可
然后还没完呢,现在编译器确实不报错了,但是呢编译不过,会出现以下问题,编译终止
神奇的事情来了,既然Version 5 is not available,我就又换回Version 6了,这次编译页面也没有报错,编译也是直接就过了。
1.include<>与include" "区别
include<>表示文件不在当前目录下,在编译器目录下
include" "表示在当前目录下找不到,再去软件目录下找
.hex:通过串口下载的可执行文件
.axf:通过编译器下载的可执行文件
.sct:加载没听清,以后补文件
下载程序
debug里选择DAP
确保Utilities里的use debug driver是勾选上的
然后在返回debug,在选择DAP的位置点击setting,在debug界面确保SWJ是勾选上的,时钟选择5MHz
切换到Flash Download界面,勾选reset and run
下载即可。如果出现这个报错,重新编译下
我实际下载的时候发现与视频中不一样,我的无法勾选SWJ,如图
去问了淘宝客服,说是版本不一样,只需connect处选择under Reset,Reset处选择SYSRESETREQ,,然后再次下载,就能成功了。
2.屏蔽 #if 0
#else
# end if
点亮LED灯
点灯三部曲
// 1.打开时钟 在AHB上
// 2.设置输出模式 GPIOx_CRL
// 3.开灯 用CDR设置指定位置为0
步骤
图 3 指南者原理图
(1)由图可知,PB0控制灯,PB0为0,灯亮
PB0通过GPIOB_ODR第0位控制
复位值为0x0000 0000,所以低十六位全是0
*(unsigned int*) (0x40010C0C) & =~(1<<0);利用上一篇最后的清零操作
这一部相当于
(2)显然光有这一步等还是不会亮,这是由于PB0目前是输入状态,不是输出状态,需改变输入状态
此寄存器四位控制一个IO口 ,CRL思维控制的一个io口,相当于ODR寄存器里的pb0
由下方每一位的解释来选择模式,LED一般用推挽输出,所以CNF选择00,MODE选择01(此位置选择没有固定原因,就是随机选择)
*(unsigned int*)0x40010C00 |=((1)<<(4*0));//最后一位置一
这行刚开始代码我一直理解的不太好,找淘宝客服battle半天,后面发现按我的理解完全可以实现视频里的结果,并且作业中的点亮其他灯也完美实现,所以我觉得我的理解没有问题
这里说一下我的理解,确实是像视频里说的一样四个一组,
*(unsigned int*)0x40010C00 |=((1)<<(4*0));这行代码在我这边是这样的
*(unsigned int*)0x40010C00 |=((0x01)<<(4*0));相当于是0001这个整体左移了4个0;
在CRL寄存器里,四位对因一个PBx,如图
所以在程序里我这行代码是这样写的(*(unsigned int*)(0x40010C00))|= ((0x01)<<(0*(4*1)));
(3)加上这一步以后,灯还是不能点亮,这是因为GPIO时钟被关闭
所以还要将时钟使能
可知0时钟关闭,所以要置一,地址为0x40021018,IOPB在第三位,所以左移三位置一
*(unsigned int*)0x40021018 |=(1<<3);
整体代码如下
作业
作业需要注意的是,灯对应的引脚不一样,其对应的CRL寄存器的位不一样,记得改CRL的值
点灯代码如下
//点亮蓝灯
//记得改CRL输出端口,不然输出端口一直是PB0,亮什么蓝灯啊
(*(unsigned int*)(0x40021018))|=(1<<3);
(*(unsigned int*)(0x40010C00))|= ((0x01)<<(4*1));//配置低寄存器CRL 模式为 0001 PB0的端口
//(*(unsigned int*)(0x40010C0C)) |=(1<<0); 可以不需要,因为CRL输出端口变了
(*(unsigned int*)(0x40010C0C)) &=~(1<<1);
//点亮红灯
//打开时钟 APB2 外设时钟使能寄存器(RCC_APB2ENR)
(*(unsigned int*)(0x40021018))|=(1<<3);
(*(unsigned int*)(0x40010C00))|= ((0x01)<<(5*(4*1)));//配置低寄存器CRL 模式为 0001 PB1的端口
(*(unsigned int*)(0x40010C0C)) &=~(1<<5);
延时函数
原因是函数写道main函数以后,并且没在main前声明
void mydelay(int dy)
{
int i=0;
int j=0;
for(i=0;i<dy;i++)
{
for(j=0;j<1000;j++)
{
}
}
}
蓝灯闪烁
//蓝灯闪烁
(*(unsigned int*)(0x40021018))|=(1<<3);
(*(unsigned int*)(0x40010C00))|= ((0x01)<<(4*1));
while(k<10){
(*(unsigned int*)(0x40010C0C)) &=~(1<<1);//点蓝灯
mydelay(500);
(*(unsigned int*)(0x40010C0C)) |=(1<<1);//关蓝灯
mydelay(500);
k++;
}
绿蓝红依次闪烁
(*(unsigned int*)(0x40021018))|=(1<<3);
while(k<10){
(*(unsigned int*)(0x40010C00))|= ((1)<<(4*0));
(*(unsigned int*)(0x40010C0C))&=~(1<<0);//点绿灯
mydelay(500);
(*(unsigned int*)(0x40010C0C)) |=(1<<0); //关闭绿灯
mydelay(500);
(*(unsigned int*)(0x40010C00))|= ((0x01)<<(4*1));
(*(unsigned int*)(0x40010C0C)) &=~(1<<1);//点蓝灯
mydelay(500);
(*(unsigned int*)(0x40010C0C)) |=(1<<1);//关蓝灯
mydelay(500);
(*(unsigned int*)(0x40010C00))|= ((0x01)<<(5*(4*1)));
(*(unsigned int*)(0x40010C0C)) &=~(1<<5);//点红灯
mydelay(500);
(*(unsigned int*)(0x40010C0C)) |=(1<<5);//关红灯
mydelay(500);
k++;
}
优化版,在h文件中声明好地址
//基地址 #define PERIPH_BASE ((unsigned int)0x40000000) //总线基地址 AHB APB1 APB2 #define APB1PERIHP_BASE PERIPH_BASE //((unsigned int)0x40000000) #define APB2PERIHP_BASE (PERIPH_BASE + 0x10000) //((unsigned int)0x40000000 + 00010000) #define AHBPERIHP_BASE (PERIPH_BASE + 0x20000) //AHB前三位为保留,单独定义,从0x20000开始定义
GPIO功能概述
全称:General purpose input output,软件可控制的引脚
1.GPIO包含在引脚内部
2.查找stm32数据手册
功能框图