之前的博客《STM32CubeMX开发环境搭建及示例》已经搭建好了开发环境,但是在开发的过程中总是忘记STM32CubeMX是如何配置工程的,所以这里随手记录一下,本篇博客会随着自己的学习不定时更新。

STM32CubeMX工程配置——以STM32F103C8T6为例

  • 下载接口配置
  • 晶振配置
  • 生成工程
  • 串口配置
    • 基本配置
    • 重定向printf到串口1
  • ADC配置
    • 单通道模式
    • 多通道模式
  • DMA配置
  • IIC配置
  • CAN配置
    • 基本配置
    • 使能CAN中断
    • 编写CAN1收发测试代码
  • 定时器配置

下载接口配置

晶振配置


我之所以这么选择,是因为我在High Speed Clock这个接口上外接了一个8Mhz的晶振

生成工程

  1. copy all used libraries into the projectfolder:复制所有库文件(不管工程需要用到还是没用到)到生成的工程目录中,此做法可以使在不使用Cubemx或者电脑没有安装cubemx,依然可以按照标准库的编程习惯调用HAL库函数进行程序编写。

  2. Copy only the necessary library files: 只复制必要的库文件。这个相比上一个减少了很多文件。比如你没有使用CAN、SPI…等外设,就不会拷贝相关库文件到你工程下。

  3. Add necessary library files as reference in the toolchain projectconfiguration file:在工具链项目配置文件中添加必要的库文件作为参考。这里没有复制HAL库文件,只添加了必要文件(如main.c)。相比上面,没有Drivers相关文件。

  1. Generate peripheral initialization as a pair of’.c/.h’ files perperipheral:每个外设生成独立的.C .H文件,方便独立管理。不勾:所有初始化代码都生成在main.c勾选:初始化代码生成在对应的外设文件。 如UART初始化代码生成在uart.c中。

  2. Backup previously generated files whenre-generating:在重新生成时备份以前生成的文件。重新生成代码时,会在相关目录中生成一个Backup文件夹,将之前源文件拷贝到其中。

  3. keep user code when re-generating:重新生成代码时,保留用户代码(前提是代码写在规定的位置。也就是生成工程文件中的BEGIN和END之间。否则同样会删除。后面会根据生成的工程进行说明)

  4. delete previously generated files when not re-generated:删除以前生成但现在没有选择生成的文件比如:之前生成了led.c,现在重新配置没有led.c,则会删除之前的led.c文件。(此功能根据自身要求进行取舍)

串口配置

基本配置

HAL_UART_Transmit():串口发送数据,使用超时管理机制
HAL_UART_Receive():串口接收数据,使用超时管理机制
HAL_UART_Transmit_IT():串口中断模式发送
HAL_UART_Receive_IT():串口中断模式接收
HAL_UART_Transmit_DMA():串口DMA模式发送
HAL_UART_Transmit_DMA():串口DMA模式接收

串口发送数据:

HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

功能:
串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。

参数:

  • UART_HandleTypeDef huart:UART结构体( huart1)
  • pData:需要发送的数据
  • Size:发送的字节数
  • Timeout:最大发送时间,发送数据超过该时间退出发送

重定向printf到串口1

/* USER CODE BEGIN 1 */
#if 1
#include <stdio.h>int fputc(int ch, FILE *stream)
{/* 堵塞判断串口是否发送完成 */while((USART1->SR & 0X40) == 0);/* 串口发送完成,将该字符发送 */USART1->DR = (uint8_t) ch;return ch;
}
#endif
/* USER CODE END 1 */

ADC配置

单通道模式

HAL_ADCEx_Calibration_Start(&hadc1);//开启ADC校准
HAL_ADCEx_Calibration_Start(&hadc2);
//=============================================================================
//函数名称:Adc_Battery()
//功能概要:读取电池电压值
//参数说明:无
//函数返回:无
//=============================================================================
void Adc_Battery(void)
{HAL_ADC_Start(&hadc2);//启动ADC装换HAL_ADC_PollForConversion(&hadc2, 5);//等待转换完成,第二个参数表示超时时间,单位ms.if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2), HAL_ADC_STATE_REG_EOC)){Battery = HAL_ADC_GetValue(&hadc2);//读取ADC转换数据,数据为12位Battery = (float)Battery*(3.300/4096)*1000;Battery = Battery*4.0;}
}

多通道模式

DMA配置

DMA Request : DMA传输的对应外设

注意: 如果你是在DMA设置界面添加DMA 而没有开启对应外设的话 ,默认为MENTOMEN

Channel:DMA传输通道设置
DMA1:DMA1 Channel 0~DMA1 Channel 7
DMA2:DMA2 Channel 1~DMA2 Channel 5

Dirction : DMA传输方向
四种传输方向:
外设到内存 Peripheral To Memory
内存到外设 Memory To Peripheral
内存到内存 Memory To Memory
外设到外设 Peripheral To Peripheral

Priority: 传输速度
最高优先级 Very Hight
高优先级 Hight
中等优先级 Medium
低优先级;Low

DMA传输模式

Normal:正常模式 当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次

Circular: 循环模式 传输完成后又重新开始继续传输,不断循环永不停止

Increment Address:地址指针递增(上方有介绍)。

左侧Src Memory 表示外设地址寄存器 功能:设置传输数据的时候外设地址是不变还是递增。如果设置 为递增,那么下一次传输的时候地址加Data Width个字节

右侧Dst Memory 表示内存地址寄存器 功能:设置传输数据时候内存地址是否递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节

//=============================================================================
//函数名称:DMA_Adc_collect()
//功能概要:读取DMA_AD值
//参数说明:无
//函数返回:无
//=============================================================================
void DMA_Adc_collect(void)
{uint8_t r,i,m;for(r=0; r<12; r++)//行{HAL_GPIO_WritePin(GPIOA, R_A_Pin, Row_A[0]);HAL_GPIO_WritePin(GPIOA, R_B_Pin, Row_B[0]);HAL_GPIO_WritePin(GPIOA, R_C_Pin, Row_C[0]);HAL_GPIO_WritePin(GPIOA, R_D_Pin, Row_D[0]);delay_us(50);HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_ConvertedValue, 4);delay_us(50);for(i=0;i<4;i++){m = Row_list[i];//列顺序VoltageS[r][m]=(uint16_t)((float)ADC_ConvertedValue[i]/4096*3.300*1000)%10000;}}
}

IIC配置


这里设置I2C传输速率为400000,是因为这里是针对MPU6050设置的,6050可支持400Khz的IIC通信接口。

因为我们的硬件IIC 芯片一般都是主设备,也就是一般情况设置主模式即可

Master  features  主模式特性

  1. I2C Speed Mode: IIC模式设置 快速模式和标准模式。实际上也就是速率的选择。

  2. I2C Clock Speed:I2C传输速率,默认为100KHz

Slave  features  从模式特性

  1. Clock No Stretch Mode: 时钟没有扩展模式
    IIC时钟拉伸(Clock stretching) clock
    stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行.clock
    stretching是可选的,实际上大多数从设备不包括SCL驱动,所以它们不能stretch时钟.

  2. Primary Address Length selection: 从设备地址长度 设置从设备的地址是7bit还是10bit大部分为7bit

  3. Dual Address Acknowledged: 双地址确认

  4. Primary slave address:  从设备初始地址

CAN配置

以下内容主要参考《STM32CubeMX | 36 - 使用CAN总线进行双板通信(TJA1050)》。

基本配置

配置CAN控制只需配置波特率,一般为500KHz,最高1MHz,其它保持默认即可。

CAN总线的波特率比较特别,串口协议的波特率只支持一个确定值,而CAN总线的波特率支持一个较宽的范围,这也使得CAN总线的抗噪声性能大大增强。

CAN总线的波特率计算方式如下:

① 确定CAN外设连接的外设总线时钟PCLK1

此处CAN1连接到APB1外设总线上,在配置HCLK=72Mhz的基础上,PCLK=36Mhz。

② 确定分频系数

此处将PCLK1进行7分频,为 36Mhz / 6 = 6Mhz,所以设置CAN1外设的分频系数为6:

③ 配置位段时序

CAN协议的每一个数据位都分为许多时间段,如图:

同步段(SYNC_SEG):位变化应该在此时间段内发生,只有一个时间片的固定长度(1 x tq);
位段1(BS1):定义采样点的位置,其持续长度可以在 1 到 16 个Tq之间调整;
位段2(BS2):定义发送点的位置,其持续长度可以在1 到 8 个Tq之间调整;
同步跳转宽度(SJW):定义位段加长或缩短的上限,它可以在 1 到 4 个Tq之间调整;

目标波特率是500khz,设:
BS1+BS2+SJW=TBS1+BS2+SJW=T BS1+BS2+SJW=T
根据:
6Mhz/T=6000khz/T=500khz6Mhz/T=6000khz/T=500khz 6Mhz/T=6000khz/T=500khz
计算出:
T=12T=12 T=12
最后在BS1、BS2、SJW的每个范围内,调整出和为12即可,配置如下:

使能CAN中断

编写CAN1收发测试代码

①编写CAN过滤器配置函数
在 CAN 协议中,发送节点将报文广播给所有接收器。而接收节点会根据报文标识符的值来确定节点是否需要该消息,为了简化软件的工作, STM32 的 CAN 外设接收报文前会先使用过滤器检查,只接收需要的报文到 FIFO 中。

STM32的CAN控制器一共有 28 个过滤器,CAN1 和 CAN2 共用这些过滤器。

CAN过滤器结构体定义在stm32f4xx_hal_can.h文件中,在main.c中编写CAN过滤器配置函数(不进行任何过滤):

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* CAN过滤器配置函数 */
static void CANFilter_Config(void)
{CAN_FilterTypeDef  sFilterConfig;sFilterConfig.FilterBank = 0;                       //CAN过滤器编号,范围0-27sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //CAN过滤器模式,掩码模式或列表模式sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //CAN过滤器尺度,16位或32位sFilterConfig.FilterIdHigh = 0x000 << 5;            //32位下,存储要过滤ID的高16位sFilterConfig.FilterIdLow = 0x0000;                  //32位下,存储要过滤ID的低16位sFilterConfig.FilterMaskIdHigh = 0x0000;         //掩码模式下,存储的是掩码sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = 0;               //报文通过过滤器的匹配后,存储到哪个FIFOsFilterConfig.FilterActivation = ENABLE;         //激活过滤器sFilterConfig.SlaveStartFilterBank = 0;if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) {Error_Handler();}
}
/* USER CODE END 0 */

其中,不同配置模式下四个数据成员内容对应的含义:

② 定义接收和发送消息变量
在main.c文件中定义CAN接收和发送消息变量:

/* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
static CAN_TxHeaderTypeDef        TxMessage;    //CAN发送的消息的消息头
static CAN_RxHeaderTypeDef        RxMessage;    //CAN接收的消息的消息头
/* USER CODE END PV */

③ 编写CAN接收中断处理函数
在main.c文件的最后编写CAN接收中断处理函数:

/* USER CODE BEGIN 4 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{uint8_t  data[8];HAL_StatusTypeDef status;if (hcan == &hcan1) {  status = HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessage, data);if (HAL_OK == status){                                       printf("--->Data Receieve!\r\n");printf("RxMessage.StdId is %#x\r\n",  RxMessage.StdId);printf("data[0] is 0x%02x\r\n", data[0]);printf("data[1] is 0x%02x\r\n", data[1]);printf("data[2] is 0x%02x\r\n", data[2]);printf("data[3] is 0x%02x\r\n", data[3]);printf("<---\r\n");}}
}
/* USER CODE END 4 */

④ 编写CAN发送测试数据函数

/* CAN 发送数据测试函数 */
void CAN1_Send_Test()
{uint8_t data[4] = {0x01, 0x02, 0x03, 0x04};TxMessage.IDE = CAN_ID_STD;     //设置ID类型TxMessage.StdId = 0x222;        //设置ID号TxMessage.RTR = CAN_RTR_DATA;   //设置传送数据帧TxMessage.DLC = 4;              //设置数据长度if (HAL_CAN_AddTxMessage(&hcan1, &TxMessage, data, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK) {Error_Handler();}
}

⑤ 编写初始化函数
修改main函数,在其中配置CAN滤波器、启动CAN控制器、使能CAN控制器接收中断:

 /* USER CODE BEGIN 2 *//* 1. CAN Filter Config */CANFilter_Config();/* 2. CAN Start */if (HAL_CAN_Start(&hcan1) != HAL_OK) {Error_Handler();}/* 3. Enable CAN RX Interrupt */if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {Error_Handler();}/* USER CODE END 2 */

定时器配置

首先查看时钟树:

定时器的时钟来自于内部的PLL分频->AHB->APB1或2(到底是APB1还是2,需要查手册,或者源码中的宏,如下图可见,2/3/4是在APB1上的,如下图可见,1是在APB2上的)


定时器溢出时间的计算:
T=((period+1)∗(psc+1))/(TIM_CLK_Mhz/TIM_ClockDivision)T=((period+1)*(psc+1))/(TIM\_CLK\_Mhz / TIM\_ClockDivision) T=((period+1)∗(psc+1))/(TIM_CLK_Mhz/TIM_ClockDivision)

period:周期寄存器TIMx->Arr的值,

psc:预分频寄存器TIMx->PSC的值,

TIM_CLK_Mhz:定时器的时钟源频率

TIM_ClockDivision:再分频系数


T=(7200∗5000)/(72000000∗1)=0.5sT = (7200*5000)/(72000000*1)=0.5s T=(7200∗5000)/(72000000∗1)=0.5s

至此配置已全部完成。

不过要想在程序里用起来,还得再写几行代码:

在main中添加一行代码:启动定时器+定时器中断

HAL_TIM_Base_Start_IT(&htim1);

STM32CubeMX工程配置——以STM32F103C8T6为例相关推荐

  1. STM32CubeMX——GPIO配置

    STM32CubeMX--GPIO配置 说明 GPIO-output 配置部分 新建工程 配置系统时钟 配置GPIO引脚(以PB15为例) 配置时钟树 项目文件设置 代码部分 函数说明 应用举例 GP ...

  2. STM32CubeMX——定时器配置

    基于STM32CubeMX的定时器配置 说明 定时器简介 基本定时器功能(TIM6.TIM7): 通用定时器(TIM2~TIM5)的主要功能: 高级定时器(TIM1,TIM8)的主要功能: STM32 ...

  3. STM32CubeMX简单配置流程

    文章目录 前言 1.创建工程 2.创建STM32F103C8Tx系列工程 3.首先配置系统下载口(STLINK) 4.配置外部时钟 5.配置相应功能 6.系统时钟配置 7.工程设置1 8.工程设置2 ...

  4. 细聊 Cocoapods 与 Xcode 工程配置

    前言 文章比较长,所以在文章的开头我打算简单介绍一下这篇文章将要讲述的内容,读者可以选择通篇细度,也可以直接找到自己感兴趣的部分. 既然是谈 Cocoapods,那首先要搞明白它出现的背景.有经验的开 ...

  5. pom.xml设置mysql连接_maven工程配置pom.xml实现mybatis的访问数据库操作

    pom.xml配置: pom.xml 这个配置还有不足请在下方给出建议 I:  我这里测试三个 : 分别是有@的 DemoMapper(接口): IDemoMapper.interface packa ...

  6. STM32F103ZET6的芯片工程改为STM32F103C8T6的工程

    STM32F103ZET6的芯片工程改为STM32F103C8T6的工程 文章目录 STM32F103ZET6的芯片工程改为STM32F103C8T6的工程 前言 1.准备工作 2.启动文件选择 3. ...

  7. 金仓数据库KingbaseES客户端编程接口指南-DCI(3. DCI 工程配置)

    3. DCI 工程配置¶ Windows 平台工程搭建(vs2008) Linux平台工程搭建 服务的配置方法与参数说明 多主机地址配置 3.1. Windows 平台工程搭建(VS2008) 3.2 ...

  8. STM32CubeMX——环境配置以及实例编译烧写

    一.STM32CubeMX环境配置 1.安装STM32CubeMX 官网下载:https://www.st.com/content/st_com/en/products/development-too ...

  9. YOLOv4 资源环境配置和测试样例效果

    YOLOv4 资源环境配置和测试样例效果 基本环境:cuda=10.0,cudnn>=7.0, opencv>=2.4 一.下载yolov4 git clone https://githu ...

最新文章

  1. 奖金+大赛入门,来参加我们的论文有奖复现!
  2. CMU提出「十字绣网络」,自动决定多任务学习的最佳共享层
  3. html5该怎么样学习?零基础入门HTML5学习路线
  4. 多继承-概念、语法和基本演练
  5. openHEVC 编译 for VS2017+Win10 x64
  6. Spring 使用context:annotation-config的设置
  7. javascript操作dom的一些函数
  8. java import 出错,Eclipse的java代码出错:The import XXXX cannot be resolved
  9. 扩容是元素还是数组_Java中对数组的操作
  10. if __name__ == __main___python中 __name__ == #x27;__main__#x27; 有什么作用?
  11. java基础-java语言中的关键字总结
  12. 蓝桥杯 ADV-155 算法提高 上帝造题五分钟
  13. Python 06 编码
  14. kmem_cache_alloc核心函数slab_alloc_node的实现详解
  15. 373.查找和最小的K对数字
  16. HDU 1394 求逆序数(线段树)
  17. drools规则引擎源码解析
  18. java100道逻辑题及答案_100道Java面试题收集整理及参考答案
  19. Cisco(思科)路由器端口的配置
  20. html书签导入苹果,如何把360浏览器的收藏书签导入safari浏览器里

热门文章

  1. ECSHOP和SHOPEX快递单号查询国际EMS插件V8.6专版
  2. ucosii的实时操作系统(任哲)——第一章
  3. 区块链如何深刻变革现代金融?
  4. 基于opengl绘制场景地形漫游:鱼+池塘+树+房屋建筑+喷泉+地形
  5. Python第三阶段学习 Django day06
  6. 排队叫号python编程_排队叫号系统示例文档
  7. BeagleBone学习(一) SD卡的烧录与扩容
  8. 以前没有煤气和天然气,城市人口是怎么做饭的?
  9. 监听当点击微信等app的返回按钮或者浏览器的上一页或后退按钮的事件
  10. (28)【xss工具绕过】xss之burpsuite、前端、字典……