技术标签: stm32 物联网 嵌入式硬件 通用微控制器(MCU)开发 嵌入式开发 单片机
本篇文章介绍了使用Keil来对STM32F103C8芯片进行初始工程搭建,以及开发与工程调试的完整过程,帮助读者能够在实战中体会到Keil这个开发环境的使用方法,了解一个嵌入式工程从无到有的过程,并且具备快速搭建一个全新芯片对应最小软件工程的基本能力思路。文章首先介绍了基础工程搭建的过程,包括代码的组织以及Keil嵌软工程配置,然后讲述了一个简单功能的开发,最后介绍了Keil环境下提供的代码调试工具以及一些常用工具配置项。
目录
Keil(全称Keil µVision IDE)是一款集成开发环境(IDE),主要用于嵌入式系统的开发。Arm Keil MDK(Microcontroller Development Kit)是面向基于Arm的微控制器的最全面的软件开发解决方案,包括创建、构建和调试嵌入式应用所需的所有组件。主要可以分为MDK(IDE以及芯片对应编译器等)、Softwarepacks(可以随时添加软件包,这使得新的设备支持和中间件更新独立于工具链)、Debug Probes(MDK 支持许多不同的调试和跟踪适配器)。
下面介绍一下后面工程搭建以及开发调试涉及的相关概念。
建立工程文件夹,在工程文件夹下建立以下目录结构,组织工程代码(可根据公司规定对工程目录结构进行统一修改)。
目录名称 | 存放文件 | 文件来源 |
Startup | startup_stm32f10x_md.s | STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3\ DeviceSupport\ST\STM32F10x\startup\arm |
CMSIS | core_cm3.c、core_cm3.h | STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\CMSIS\CM3 \CoreSupport |
Libraries | 芯片外设标准库文件 | STM32F10x_StdPeriph_Lib_V3.6.0\Libraries\STM32F10x _StdPeriph_Driver |
App | 1.用户编写的业务代码,可根据业务创建子目录。 2.main.c、stm32f10x_conf.h、stm32f10x_it.c、system_stm32f10x.c |
1.用户编写/移植。 2.STM32F10x_StdPeriph_Lib_V3.6.0\Project\STM32F10x_ StdPeriph_Template |
Bulid | 用来存放编译生成文件 | Keil编译生成。 |
首先打开Keil5,新建工程,芯片型号选择STM32F103C8。随后弹出在线添加库文件,关闭即可。如下图所示。
然后点击三色块用来添加工程目录,并添加相关目录,增加待编译源文件。如下图所示。
最后,单击魔术棒进行配置,这部分的配置比较多,下面分步逐一进行介绍。
最后,如果配置正确,相关的文件也都正确添加至工程内,编译之后就会在Build Output看到生成了可以下载执行的hex文件,如果没有需要我们根据错误信息来逐步解决。
首先我们需要安装JLINK驱动(segger上或者百度),如果驱动安装成功,将设备usb接口插到电脑上后,绿灯转为常亮,电脑的设备管理在通用串行控制器中能够识别到仿真器。然后我们需要按照JTAG接口引脚定义正确将仿真器与板卡相连。
最后,我们需要在Keil中根据我们仿真器类型正确配置Debug信息如下,并选择相关仿真器窗口。
这是如果仿真器能够正常连接到板卡,绿灯会闪烁,点击Settings摁扭能看到识别到的芯片核心,如果不正常则会为空白。
我们开发一个串口打印的功能,因为只是一个demo,所以我们将串口初始化的部分也放到main.c里,下面是main.c的代码。
#include "stm32f10x.h"
#include "usart.h"
void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
void USART1_IRQHandler(void)
{
u8 Data;
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
{
Data = USART1->DR;
}
}
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(USART1, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return (ch);
}
int main(void)
{
uart_init(9600);
while(1)
{
printf("STM32\n");
}
}
然后点击编译,生成可执行文件之后点击下载到板卡。
最后正确连接板卡上的串口线到串口小板(TTL转USB),打开串口调试助手,就能看到板卡打印出来的串口信息。
点击红色那个上面有个红色字母d的小放大镜摁扭,就会下载程序并进入仿真模式,这个时候程序停在起始位置。
按照上图的标号,我们介绍一下相关区域的作用。
还有一些比较常用的调试窗口。memory窗口可以看指定区域的存储器数值,正如上面提到的存储指令,我们也可以通过memory窗口看到对应的内容。
还有就是Watch窗口,可以添加一些变量,在调试过程中观察变量的变化。
最后一个常用的就是系统外设窗口,在调试过程中可以看到具体对应外设的寄存器值。
keil默认无法显示中文,输入中文时,出现的是问号。可以将Edit-->Configuration中的编码改成GB2312解决这个问题,同时在这个页签中可以将Tab设置为4个空格。在Configuration还有更多诸如字体等环境配置,读者可以根据自己的喜好来进行调整。
十六宿舍 原创作品,转载必须标注原文链接。
2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个,更多关于嵌入式相关技术的内容持续更新中。
文章浏览阅读2.9k次。不知到有没有人遇到过这种情况:就是在Qt Designer中新建一个窗口后,然后添加控件后,为了使控件随窗口变大而一起变大,需要对整个窗口进行一个布局才可以。但是布局后,在Qt Designer中预览是可以的,而到了Pycharm等编辑器中运行就不行了,如下图所示:可以看到,在Pycharm中运行后按钮都缩在一块,而且也不会像预览里那样自适应窗口放大。这个真的很费解,花了一天才弄明白,其实..._qt-designer中,在多个frame的情况下,frame中的控键为什么不能自适应变化
文章浏览阅读1.2w次。1、jquery安装<head> <script src="jquery-1.10.2.min.js"></script> </head>2、jquery语法基础语法:$(selector).action()美元符号定义 jQuery 选择符(selector)"查询"和"查找" HTML 元素 jQuery 的 action(..._jquery 菜鸟教程
文章浏览阅读4.4w次,点赞17次,收藏7次。1.问题背景: 某些时候会接收到别人发给我们的xmind(一种思维导图)的文件,但苦于我们的电脑上没有下载Xmind软件,所以我们怎么快捷的查看该文件的内容呢?2.解决方案:Step 1: 我在网络上搜索了相关的解决方法,发现一个比较快捷的,因此推荐给大家,就是我们可以直接使用百度脑图 (https://naotu.baidu.com/)来直接打开xmind类型文件。 首先我们需要登录我们的百度账号进去,然后就进入到了以下界面:Step 2: 然后我们点击新建脑图,然后再直接点击这_xmind在线打开
文章浏览阅读480次。1、project路径名必须是纯英文。空格不知道能不能有,大家还请自己试试,这也是我自己出的问题。2、这必须是个project而不是单一的一个cpp文件。其实这已经隐含在1里面了3、本身没有打开编译器的-g标志。这个比较隐蔽,但是我试了试好像没有什么影响,大家要是1,2都试了不行可以再看看这个。具体方法:在Settings->Complier and debugger->Global complier settings->Complier settings->Complier f_codeblock断点不停
文章浏览阅读857次,点赞23次,收藏18次。范围for、new内存动态分配、nullptr
文章浏览阅读1.5k次。lightoj 1268 Unlucky Strings (矩阵快速幂+kmp DFA 好题)_unlucky string
文章浏览阅读4.9k次,点赞7次,收藏32次。我们通常使用ROC曲线来评价分类结果的好坏,在MATLAB中绘制该曲线其实也十分容易。我们让label表示真实的类别,output表示预测的类别,那么调用:[XRF,YRF,TRF,AUCRF] = perfcurve(label,output,1);之后运行:plot(XRF,YRF)即可得到ROC曲线,该函数中还有一个参数,也就是正类的标签(positive class label),该变量是一个常数,可以为数值,也可是是字符串等,需要指定一下。上面的例子中,我们输出的结果和标签都是0或1的_matlab roc
文章浏览阅读4.3k次,点赞2次,收藏16次。线性分组码假设信源输出为有限域GF(2)上连续的二元符号序列,称为消息序列。在分组码中每一个消息分组含有k个信息比特,一共有2k个不同的消息,对应2k个不同的码字。所有码字的集合构成一个(n,k)分组码。其中参数n称为码长,k称为码的维度或消息长度,由编码器产生的n-k个添加到每个输入消息中的消息比特称为冗余比特。码率R=k/n,可以解释为每一个码比特所携带的平均信息比特数。1. 最小汉明距离汉明重量:表示一个码字中非零元素的个数。重量分布:用Ai表示分组码中汉明重量为i的码字数,数A0,A1,_移动通信中常用的信道编码方法有哪些?
文章浏览阅读332次。432行,改了一下之前的节流函数,将时间从20ms改到了16ms,原因是一般计算机显示器的刷新率都是60HZ,也就是浏览器每秒需要重绘60次,用1秒除以60,也就是1000ms/60,约等于16.6666667,那么最合适的重绘间隔也就是16ms或者17ms,这个时间能实现最平滑的动画过渡效果,如果低与这个值,用户也感知不到,且会造成浪费性能,所以16ms最合适。446、453行,2.15.9版本中,把表头绑定的事件和解绑事件函数换成了自己写的一个onScroll函数。_table 横向滚动 有延迟
文章浏览阅读74次。145. 二叉树的后序遍历说明给定一个二叉树,返回它的 后序 遍历。示例输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1]题解思路1、递归2、迭代,利用栈代码实现1、递归# Definition for a binary tree node.# class TreeNode:# def __init__(self, val=0, left=None, right=None):# sel_def postordertraversal(self,root: treenode) -> list[int]: def dfs(root): if
文章浏览阅读2.2k次,点赞2次,收藏12次。首先小吐槽一下,本人强烈不推荐使用Mendeley,本来以为Mendeley是一个不错的软件,而且自带pdf标注,但这恰巧也成为它的劣势,在Android和PC上互相同步过程中发现,高亮的部分,发生了偏移,讽刺的是,居然高亮到了文字旁的空白部分,我忍无可忍,售后只告知,重装,但是这个bug依然存在。当然如果你只用PC,不用Android版,那问题不大。折腾Mendeley浪费了我大量的时间,非常不爽,所以投身Zotero,开源软件才有强大的生命力。言归正传,本篇文章主要是为了给新入门Zotero的用户一_zetero
文章浏览阅读3.5k次。一:@PropertySourceSpring boot框架提供了@PropertySource注解,目的是加载指定的属性文件,接下来我们看一下如何使用该注解。首先在默认的application.properties文件中添加如下内容spring.datasource.url=jdbc:mysql://192.168.10.171:3306/Steam?useUnicode=tru..._spring.datasource.url integratedsecurity