完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1 Install&Configuration
1.1 Package 官网 https://www.keil.com/download/product/ 提供了MDK-Arm免费下载 作者这里使用了5.23版本的MDK。 1.2 Install 双击安装包,进行安装前的准备,遇到下图选择同意。 安装路径选择,作者直接默认全部安装在C盘。 客户信息只需格式正确即可。 安装过程中,会自动请求安装一些驱动,若在不知该驱动为什么服务的话,一律选择安装即可。 安装完成则会弹出下面界面,不用选择Show Release Notes,直接Finish。 1.3 License 安装 打开keil—>File —>License Management进行license安装,复制CID,使用CID得到LIC 填入LIC,点击Add LIC,关闭窗口。 第一次打开keil,会弹出设备包安装工具(若没弹出看下一步),点击OK,该工具在线安装需要等待片刻,左边会加载完整安装目录。 如果无意关了该界面或者未弹出,可以在直接打开keil,点击如下指示的图标。 加载完毕后选择我们需要的芯片(这里为STMicroelectronics —>STM32F1 Series—>STM32F103 —>STM32F103RB)。然后找到DFP文件进行安装(这里为STM32F1xxDFP) 至此安装过程完毕,打开keil。 2 Start a New Project 2.1 New Project 进入keil后如下所示。 开始新建一个工层,打开project —>New uVersion Project。 选择合适的文件夹保存工程,注意新建工程不会新建根目录,该文件夹会被完全占用。 保存后,选择芯片 OK之后会出现库配置,在这里选择的话,既不用配置复杂的启动文件,分组,头文件,宏定义等,而且功能十分强大,包含了大量的库文件,而且还有依赖校验功能帮助使用者选择合适的库文件。 如下,为一个一个简单的模板工程配置了必须的CMSIS中的CORE,Device中的Startup和StdPeriph Drivers文件夹下的所有文件,这些库文件在工程进行中也可以更改,也可以在工程完成后去掉不必要的库,节省Flash空间。 加入好库文件的工程如下 然后把我们自己的,工程必须的main.c文件加入进去。首先新建一个空白main.c文件。 保存在项目文件夹下一个合适的地方(作者保存在了工程根目录下)。 然后还需要将main.c 文件加入到工程,直接右击Target选择Manage Project items…,进入管理界面 如下为管理界面,其中三个栏目下的内容皆可自由编辑。 我们把main.c添加到Target 1的Source Group 1中,直接点击Add Files。 添加进去后,如下所示。需要注意的是,以后添加进工程的任何c文件皆需要这一步来添加进来,多的话可以在Group栏目下多分几个组。而头文件只需要加入路径即可,操作方法在后面会提及。 然后,工程还需要一些配置。如下点击该图标进入配置界面。 首先,将Target栏中的晶振频率改为8.0MHz。 然后在Output栏下,点击上面框中按钮可以配置编译生成的文件存放于何处,可以不用配置,勾选生成HEX文件,此文件可以使用各种通用烧录软件给芯片下载程序。在此教程中不涉及该文件的使用。 可以看到生成目标文件的文件夹默认在根目录的Objects文件夹下。 然后,进行调试和烧录的配置,我们使用的调试工具为ST-LINK V2,在Debug栏下选择如下。 Utilities栏下可以选择烧录方式,我们可以不用配置其他工具,直接使用keil就好。配置如下。 然后进入如下所示的Settings(和Utilities栏中的是相同的) 确认调试工具是否正常,如下为连接正常,不同调试工具的序列号可能不一样,Port一定要选择SW,MAX不能选择太大。 接着进入另一个选项页,记得勾选Reset and Run。这样下载后会自动开始运行程序。 其他可以使用默认配置,如果有需要则按需要进入再配置。另外,新添加的头文件需要在C/C++一栏下添加路径。 如下建立并选择路径。整个项目的宏定义也在C/C++一栏下添加, 2.2 Build Project 在刚才建立的main.c中添加以下内容: #include "stm32f10x_gpio.h" void delay(vu32 nCount) { vu32 index = 0; for(index = (34000 * nCount); index != 0; index--) { } } void GPIOB_Set(uint16_t pin){ GPIO_InitTypeDef GPIO_InitStructure; /* Enable the GPIO Clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); /* Configure the GPIO pin */ GPIO_InitStructure.GPIO_Pin = pin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } int main(void){ GPIOB_Set(GPIO_Pin_0); while(1){ GPIO_SetBits(GPIOB, GPIO_Pin_0); delay(300); GPIO_ResetBits(GPIOB, GPIO_Pin_0); delay(100); } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %drn", file, line) */ /* Infinite loop */ while (1) { } } #endif 该文件的作用是让开发板的测试灯[PB0]一长一短的进行闪烁,启动部分代码在工程建立的时候就已经配置了(Startup中的汇编文件),程序开始的地方并不是main函数,而是启动文件,启动好后程序的入口才开始转入main函数。 保存后,点击build 图标或者选择project —> build,如果已经build过了,可以选择rebuild 如果出现如下信息,则说明编译链接均正常无误,可以进行下一步。 3 Debug&Flash 3.1 Debug 如下所示,点击该按钮进入调试模式,退出时同样点击该按钮。 如下图所示,keil自带的调试工具具有强大的功能,可以进行单步调试,同步汇编,断点设置,数据观察窗,逻辑分析,输出波形等等。 需要注意的是,同步调试一般不会将程序烧录给芯片,这与BOOT设置也有关。 3.2 Flash 烧录时,点击如下所示按钮即可 出现如下所示信息说明程序烧录成功,需要注意的是如果没设置烧录完毕重启的话,需要手动按下开关重启以后生效。 4 Example 4.1 Usart STM32F103有三个USART外设,下面以USART1为例,进行配置: #define USART1_GPIO GPIOA #define USART1_TX GPIO_Pin_9 #define USART1_RX GPIO_Pin_10 #define USART1_GPIO_CLK RCC_APB2Periph_GPIOA #define USART1_PORT_CLK RCC_APB2Periph_USART1 void USART1_Init(void){ USART_InitTypeDef USART_InitStructure;//usart配置结构体 GPIO_InitTypeDef GPIO_InitStructure;// usart所需引脚配置 /* Enable GPIO clock */ RCC_APB2PeriphClockCmd(USART1_GPIO_CLK, ENABLE); /* Configure USART Tx as alternate function push-pull */ //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = USART1_TX; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(USART1_GPIO, &GPIO_InitStructure); /* Configure USART Rx as input floating */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = USART1_RX; GPIO_Init(USART1_GPIO, &GPIO_InitStructure); /* Enable UART clock */ RCC_APB2PeriphClockCmd(USART1_PORT_CLK, ENABLE); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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 configuration */ USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启接收中断 //USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /* Enable USART */ USART_Cmd(USART1, ENABLE); } 通过下面的程序,可以将USART1的数据发送映射到printf函数 #include #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ struct __FILE { int a; }; FILE __stdout; void _sys_exit(int x) { } PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } 调用如下: #include int main(){ printf("nrUSART Printf Example: retarget the C library printf function to the USARTnr"); return 0; } 结果如下: 实际应用中我们需要非阻塞的接收串口数据,此处我们借助了其接收中断。 代码如下: #define RXBUF2_MAX 256 //定义为256时,uint8_t不用判断是否溢出,自动从0开始 char RxUBuf1[RXBUF1_MAX]; static uint8_t Num_U1RxByte = 0; static uint8_t U1RxF = 0; static uint8_t U1RxL = 0; char USART1_ReadByte(void){ if(Num_U1RxByte == 0) return ''; Num_U1RxByte--; return RxUBuf1[U1RxF++]; } uint8_t USART1_RecNum(void){ return Num_U1RxByte; } char USART1_SendChar(char ch){ USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } void USART1_IRQHandler(void){ if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断是否为接收中断 { RxUBuf1[U1RxL++] = USART_ReceiveData(USART1); //读取接收到的字节数据 if(Num_U1RxByte < 255)Num_U1RxByte++; else{ U1RxF++; //当buffer满了丢弃最先收到的1个数据 } } } 使用示例: int main(void){ int i = 0; GPIO_Conf(LED_PORT,LED0_PIN|LED1_PIN); USART1_Init(); while(1){ GPIO_SetBits(LED_PORT, LED0_PIN); GPIO_ResetBits(LED_PORT, LED1_PIN); delay(30); GPIO_SetBits(LED_PORT, LED1_PIN); GPIO_ResetBits(LED_PORT, LED0_PIN); delay(10); i = USART1_RecNum(); while(i--){ USART1_SendChar(USART1_ReadByte()); } } return 0; } 结果如下: 以同样的方式配置USART2,用下面的程序则可以直接通过串口调试助手跟NB-IoT模组进行通信。 int main(void){ int i = 0; GPIO_Conf(LED_PORT,LED0_PIN|LED1_PIN); USART1_Init(); USART2_Init(); NVIC_Config(); while(1){ GPIO_SetBits(LED_PORT, LED0_PIN); GPIO_ResetBits(LED_PORT, LED1_PIN); delay(30); GPIO_SetBits(LED_PORT, LED1_PIN); GPIO_ResetBits(LED_PORT, LED0_PIN); delay(10); i = USART1_RecNum(); while(i--){ USART2_SendChar(USART1_ReadByte()); } i = USART2_RecNum(); while(i--){ USART1_SendChar(USART2_ReadByte()); } } } 与NB-IoT模组通信结果如下所示: 完整的测试工程代码见:https://github.com/Magelgit/KeilforSTMF103RB |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
2094 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1824 浏览 1 评论
1299 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
849 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1889 浏览 2 评论
2089浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
996浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
380浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
713浏览 3评论
697浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-3-29 03:30 , Processed in 1.034203 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191
|