机器人工程系列文章目录
这里罗列了系列文章链接
概念总述
STM入门教学
还没写完组里急用
文章目录
- 机器人工程系列文章目录
- 概念总述
- STM入门教学
- 前言
- 串口
- 串口的概念
- cubemx
- keil5
- 实物实验
- 关于cubemx生成逻辑
- printf升级
- usart.c
- main.h
- retarget.c
- 定时器
- 定时器的概念
- cubemx
- keil5
- stm32f4xx_it.c
- 关于参考资料
- 参考库文件
- 参考数据手册
- 样例工程
- 参考别人的工程
前言
咳咳,最近出差,手边没实物,实物演示等我回实验室慢慢更
串口
串口的概念
这个东西叫串口,也叫UART或者USART,他是实现单片机交互数据的一种方式,当然可以给你的电脑提供数据交互
观察他的接口上会写着TX(transmit)与RX(receive)两个引脚,分别是他的嘴巴(TX)和他的耳朵(RX),显而易见的是如果你希望让两个单片机进行交流,你需要让A设备的RX(耳朵)接上B的TX(嘴巴),而B设备的RX(耳朵)接上A的TX(嘴巴)
cubemx
我们首先打开cubemx文件,选择Connectivity中的USART1,并设置模式为Asynchronous,观察到右侧PA9与PA10被设置为了USART1的RX与TX,点击生成代码
keil5
打开main.c文件,并在main文件中相应位置添加
/* USER CODE BEGIN 2 */uint8_t usart1_tx_buf[] = "Hello world\r\n";/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){HAL_UART_Transmit(&huart1, usart1_tx_buf, sizeof(usart1_tx_buf), 0xffff);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
编译并下载
实物实验
打开设备管理器,如果你已经正常安装了各个驱动设备,你大概能看见
打开XCOM,选择
按下单片机的RST按钮
关于cubemx生成逻辑
cubemx的功能是为了帮助你完成大部分的底层逻辑配置,并为提供大量的库函数支持。
通常cubemx会帮你修改你的工程和代码,考虑到用户和cubeMX修改的内容不同,所以文件做了区分,
对于cubeMX生成的文件而言
printf升级
HAL_UART_Transmit();看起来不是很好用,我们会想能不能像平常写C语言一样简单地输出字符。
首先打开usart.c,并在文件最下方加入
usart.c
/* USER CODE BEGIN 1 */
int sendchar (int ch){HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 0xffff);return ch;
}
/* USER CODE END 1 */
以及main.h中加入
main.h
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
在文件管理器增加retarget.c文件,并用文本编辑器加入下述文字
retarget.c
#include <stdio.h>
#include <rt_misc.h>//#pragma import(__use_no_semihosting_swi)//ARM Compiler6²»¼戝import£¬¸ĎªςæµĄځªº¯ʽ
__asm(".global __use_no_semihosting");extern int sendchar(int ch); /* in Serial.c */
//extern int getkey(void); /* in Serial.c */
extern long timeval; /* in Time.c *///struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;int fputc(int ch, FILE *f) {return (sendchar(ch));
}//int fgetc(FILE *f) {
// return (sendchar(getkey()));
//}int ferror(FILE *f) {/* Your implementation of ferror */return EOF;
}void _ttywrch(int ch) {sendchar (ch);
}void _sys_exit(int return_code) {while (1); /* endless loop */
}
回到keil中,双击Application/User/Core,将retarget.c添加到工程中,当然你也可以靠keil中的新建文件去添加,可以自己试试
接下来你可以将while里的函数做一定替换,可以更加方便的完成通讯。
/* USER CODE BEGIN 2 */uint8_t usart1_tx_buf[] = "Hello world\r\n";/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){printf("Hello World\r\n");//HAL_UART_Transmit(&huart1, usart1_tx_buf, sizeof(usart1_tx_buf), 0xffff);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
定时器
定时器的概念
比如你现在要看管一个锅炉,每一小时需要放气一次,放气的工作需要花费你一分钟。你会有以下几种情况
- 你可以拿着一个计时器,每当计满一小时后,你去放一次气,这样每次放气的循环会维持在61分钟,长期这么做设备可能就会出现损坏。
- 你可以估算下自己放气的时间,如果是一分钟的话,我用计时器计算59分钟,这样循环可以稳定在60分钟。
- 你现在不止有放气的一个任务,你还需要加煤,还需要加水,还需要写报告,而且每个任务消耗的你时间是不确定的,可能是2分钟,可能是10分钟。为了更准确保证一小时放一次气,你决定选一个闹钟,每一小时提醒你做一轮工作。
定时器的核心功能体现在可以保证任务按照一定频率的完成,实际上单片机运行过程中任务时长是不确定的,为了确定一个稳定的工作频率,定时器的引入是必须的。
cubemx
选择Timers中的TIM11,勾选Activated。
Prescaler中写为99,我们上一章设置主时钟为100Mhz,意味着单片机一刻时钟为0.01us,但通常高频会造成更高的能耗,因此需要根据实际需求进行降频并分配给子定时器。写为99实际为100,这是因为程序通常从0开始计数,因此100Mhz会被分频100转换为1Mhz,也就是1us作为时钟的一刻。
Counter Period设置为999,这意味着我们计数1000则重新开始计数,也就意味着这个定时器每1ms就会自动刷新一次。
这还不够,定时器会单独在那运行,但他不会提醒你,因此选择NVIC Setting中,设置定时器中断开启,这样每1ms都会被提醒完成一次工作。
keil5
所以中断会怎么被提醒去工作呢,在stm32
做如下修改
stm32f4xx_it.c
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{/* USER CODE BEGIN TIM1_TRG_COM_TIM11_IRQn 0 */static uint32_t counter;counter++;if(counter>999)counter=0;printf("Hello World\r\n");/* USER CODE END TIM1_TRG_COM_TIM11_IRQn 0 */HAL_TIM_IRQHandler(&htim11);/* USER CODE BEGIN TIM1_TRG_COM_TIM11_IRQn 1 *//* USER CODE END TIM1_TRG_COM_TIM11_IRQn 1 */
}
关于参考资料
写到现在比较困惑的一个问题是,这些东西我怎么理解?有哪些功能?有哪些函数?通过ST官方文件我们可以做如下了解。
参考库文件
函数右键Go to the Definition可以进入库函数定义文件,可以阅读英文注释了解函数具体使用。
参考数据手册
cubemx的Help->Docs&Resources,会有大量的stm32数据手册,可以多多参考阅读。
Description of STM32F4 HAL and low-layer drivers
样例工程
除了上述文档,ST提供了相关的工程文件作为参考
通常目录会放在
C:\用户\STM32Cube\Repository
其中的文件夹中有对应版本库的相关资料,包含了大部分HAL库与LL库的使用范例,就不用头疼的全网找资料了(一个个打开来看看吧)
参考别人的工程
学习学习别人的工作,了解了解别人如何应用设备芯片,可以帮助你更快的搭建自己的工程