STM32 系列使用知识问题笔记

2023-05-16

	STMF103用了这么多年,项目也做过不少,当然也遇到过很多问题,虽然现在使用起来也算得上得心应手,
	但是有些地方还是用起来还是得查查看看,所以就专门开设一篇文章,放一些基本笔记,方便以后查找。
	这里的笔记知识大多都是以前网上查找保存的笔记,后续维护在自己遇到问题的时候会多放些自己踩过的坑。

目录

  • 1、获取定时器时钟频率
  • 2、ADC通道对应关系
  • 3、中断优先级
  • 4、ADC采样计算
  • 5、DMA
  • 6、I2C通讯(软件I2C)
  • 7、HAL库中的串口操作
  • 8、中断操作
  • 9、位操作
  • 10、FreeRTOS中断中死机问题
  • 11、STM32 如何定义变量到FLASH 中
  • 12、 关于__attribute__((packed))
  • 13、 extern 声明结构体

1、获取定时器时钟频率

uint32_t get_time_clock_freq(TIM_TypeDef *t) {
    uint32_t time_clock_freq = 0;
    RCC_ClocksTypeDef clocks;
    RCC_GetClocksFreq(&clocks);
    if(t == TIM1 || t == TIM8) {
        time_clock_freq = clocks.PCLK2_Frequency;
        if(clocks.HCLK_Frequency/clocks.PCLK2_Frequency > 1) {
            time_clock_freq <<= 1;
        }
    } else {
        time_clock_freq = clocks.PCLK1_Frequency;
        if(clocks.HCLK_Frequency/clocks.PCLK1_Frequency > 1) {
            time_clock_freq <<= 1;
        }
    }
    return time_clock_freq;
}
————————————————
版权声明:本文为CSDN博主「矜辰所致」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42328389/article/details/118212278

2、ADC通道对应关系

在这里插入图片描述

3、中断优先级

在这里插入图片描述

4、ADC采样计算

在这里插入图片描述

5、DMA

DMA用在什么地方合适?形象地说,DMA是MCU内的搬运工,通过DMA把数据从外设和内存之间的自动搬迁,节省软件的开销。

STM32 的DMA有三种模式:内存-外设,外设-内存,内存-内存。

举几个例子:

USART串口发送:没DMA的情况,要发送大量数据,需要每一个字节发送后产生完成中断或轮询旗标,然后软件介入把下一个数据放入TDR寄存器,这样会有大量中断或等待消耗程序的资源,如果采用DMA的话,至需要预先在DMA通道设定要发送的数据的第一字节的内存地址(例如: &buf[0]), 和设定需要发送多少字节,开始发送后,DMA就会像z指针一样完成一节,指针自动递增或减自动移动数据到发送寄存器,直至发送完成会有一次中断通知。中间过程软件完全可以不介入。

ADC采集:多次采样或循环采样,同样地没DMA的话,采样完毕中断,搬移ADC的采样值,出现大量中断,如果是高速采样情况更甚。可以通过DMA采样完成后自动写入你指定的数组地址,一个循环后DMA一个完成中断通知你做后续的事情,例如平均算法之类的。

DAC波形输出:把波形的样本建立一个数组,使用DMA循环发送。

用和不用当然都可以发送。不用DMA发送是需要单片机实时参与,由单片机一个一个地发送数据并进行监控。但是如果用DMA,设置了起始地址,数据大小等参数后,就直接由专门的一个DMA模块进行数据发送,发送过程中单片机无需参与。发送完后会产生中断告知单片机。由此可知用DMA可以节省单片机资源,让单片可以在同一时间里干更多事。

6、I2C通讯(软件I2C)

起始信号:时钟线高电平的时候,数据线由高变低

void i2c_start(void)
{
   sda_high;
   delay_us(5);
   scl_high;
   delay_us(10);
   sda_low;
   delay_us(10);
   scl_low; //使SCL置低,准备发送或者接受数据
   delay_us(10);
}

结束信号:时钟线高电平的时候,数据线由低变高

void i2c_stop(void)
{ 
   sda_low;
   delay_us(5);
   scl_low;
   delay_us(10);
   scl_high;
   delay_us(5);
   sda_high;
   delay_us(10); 
}

ACK:正常的时钟周期,保持低电平,主机和从机都需要响应ACK

void IIC_Ack(void)
{
	MYIIC_CLK_LOW;    //SCL为低,SDA为低,SCL为高,SDA为低,应答低电平有效,SCL为低,产生应答信号
	// MYSDA_OUT;
	MYIIC_DATA_LOW;
	delay_us(10);
	MYIIC_CLK_HIGH;
	delay_us(10);
	MYIIC_CLK_LOW;
	/*注意,加上了下面一句,释放总线,数据才正确*/
	delay_us(10);
	MYIIC_DATA_HIGH;
}

NACK:正常的之中周期,保持高电平,一般在接收数据的最后一个字节,发送NACK,表示接收完成

void IIC_NAck(void)
{
	scl_low;     //SCL为低,SDA为高,SCL为高,SCL为低
	// MYSDA_OUT;
	sda_high;
	delay_us(10);
	scl_high;
	delay_us(10);
	scl_low;
}

在添加I2C设备的时候,读取数据时候,主机需要返回ACK给从机,但是得注意主机返回ACK最后需要释放 SDA线,在以前使用的过程中,遇到过没有释放也可以成功的例子。

但是最近在使用STM32L051添加欧姆龙 D6T-1A-02非接触温度传感器的时候遇到,如果不在返回ACK后释放SDA线控制权,从机无法正常发送数据(因为SDA先被主机拉低了,从机无法拉高):

7、HAL库中的串口操作

使用STMCubeMX生成工程后,会自动设置好NVIC中断优先级,使能了NVIC中断,在usart.c下的`void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)中有:

HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);

但是串口的接收中断,是没有自动使能的,我们需要自己使能,但是如何使能,比如:

/*USART_Enocean_BUF , USART_RX_BUF 是你的接收缓冲区*/
HAL_UART_Receive_IT(&hlpuart1, USART_Enocean_BUF, 1);
HAL_UART_Receive_IT(&huart2, USART_RX_BUF, 1);

如果你需要接收一帧数据,可以开启IDLE中断,初始化后,运行前加上
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE);
那么还有一句:
__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);
这句话是不是开启了前面的HAL_UART_Receive_IT就不需要用了呢?
实际上测试是这么回事,以前在标准库中使用串口通讯UART_IT_RXNE基本上都必须使能的,那么为什么?

在这里插入图片描述
见文章:RT-Thread 应用篇 — 在STM32L051上使用 RT-Thread (四、无线温湿度传感器 之 串口通讯)
《4.2 串口通讯细节问题》

8、中断操作

屏蔽外部中断
关闭中断
EXTI->IMR &= ~(EXTI_Linex);
打开中断
EXTI->IMR |= EXTI_Linex;

在Hal库中:

void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
{
  /* Check the parameters */
  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
  
  /* Enable interrupt */
  NVIC_EnableIRQ(IRQn);
}

/**
  * @brief  Disable a device specific interrupt in the NVIC interrupt controller.
  * @param  IRQn External interrupt number .
  *         This parameter can be an enumerator of IRQn_Type enumeration
  *         (For the complete STM32 Devices IRQ Channels list, please refer to stm32l0xx.h file)  
  * @retval None
  */
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
{
    /* Check the parameters */
  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
  
  /* Disable interrupt */
  NVIC_DisableIRQ(IRQn);
}

举例:

...
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
...
if(...){
	HAL_NVIC_DisableIRQ(EXTI4_15_IRQn); 
}

9、位操作

对寄存器的操作,使用位操作是效率最高的方式。

置位
int a = 0x123;把a的 bit 7,8位 置位:
int b = a | (1<<7) | (1<<8);

GPIOA -> ODR |=1<<5; //PA5输出 1,其他位不变

清位
int a = 0x123; 把a 的 bit7,8 清0;
int b = (a & ~( 1<<7))&(~ (1<<8));

10、FreeRTOS中断中死机问题

中断中使用printf函数死机问题,本来只是为了测试看一下,实际应用当然是在中断中不能使用printf的,但是以前确实也没有遇到死机问题,这一次在使用FreeRTOS 的时候,中断中只要使用printf就死机,程序无法调度了,具体原因还不知道,只能避免,相关部分截图先放在下面,以后如果知道答案可以来分析一下。

在中断中养成不用打印的好习惯!!!!!切记,测试可以,实际项目不可以!

硬件平台 STM32L051C8T6:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11、STM32 如何定义变量到FLASH 中

在使用AVR,8051单片机的时候,如果在变量定以前加上 code 关键字,表示 定义的数据要放在 ROM中:

code uint8 EEP_Info[EEP_TYPE_Num][2] = { 
                    					0x02,0x01,
										0x02,0x02,
										0x02,0x03,
										0x02,0x04,
										0x02,0x05
										};

那么对于 STM32 而言呢,需要加关键字 const msp430也是。

const uint8 EEP_Info[EEP_TYPE_Num][2] = { 
                    					0x02,0x01,
										0x02,0x02,
										0x02,0x03,
										0x02,0x04,
										0x02,0x05
										};

12、 关于__attribute__((packed))

在结构体后面的 attribute ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,比如:

typedef struct
{
    u8 ID1;
    u8 ID2;
    u8 ID3;
    u8 ID4;
    u8 ID5;
    u8 ID6;
    u32 state;

}__attribute__ ((packed)) BlueID_STRUCT;

不对齐,结构体的长度,就是各个变量长度的和!

当然也可以指定字节对齐(4字节对齐):

typedef struct
{
    u8 ID1;
    u8 ID2;
    u8 ID3;
    u8 ID4;
    u8 ID5;
    u8 ID6;
    u32 state;

}__attribute__ ((aligned(4))) BlueID_STRUCT;

13、 extern 声明结构体

C语言要定义外部文件可使用的结构体和结构体变量。

需要保证 extern 声明的 文件中,有结构体的定义

在这里插入图片描述所以需要改成 在 定义的文件中 声明:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32 系列使用知识问题笔记 的相关文章

  • 面向行业级应用的Kerloud 600 Pro-Cam Pod开发平台

    产品定位 Kerloud 600 Pro Cam Pod是云讷科技 xff08 深圳 xff09 有限公司为行业级无人机解决方案开发者打造的一款高级无人机研发平台 xff0c 产品搭载高算力Nvidia GPU 高清吊舱云台并配备专业的SD
  • swift-网络-URLSession学习

    URLSession 在 2013年随着 iOS7 的发布一起面世的 xff0c 苹果对它的定位是作为 NSURLConnection 的替代者 xff0c 在 iOS9 之后苹果官方已经移除了 NSURLConnection xff0c
  • nil和Nil及NULL和NSNull的区别 - OC

    其实早就想研究一下nil Nil NULL和NSNull之间的区别 xff0c 只是工作上除了nil xff0c 其它的几乎少有用到 xff0c 所以一直拖到今天 有时候感觉自己越来越浮躁 xff0c 对细微处的知识理解不够深入 xff0c
  • Fast-planner代码阅读2-TopoReplan (path searchiing部分)

    文章目录 1 总体流程2 Topo Path Finding Algorithm主要算法及图例3 topoPath路径搜索代码流程3 1 createGraph xff08 xff09 3 1 1 findVisbGUard3 1 2 ne
  • centos7.7 安装google浏览器

    centos7 7 安装google浏览器 添加google chrome 源 cd etc yum repos d vi google chrome repo 添加如下内容 google chrome name 61 google chr
  • mysql5.6漏洞_MySQL 5.6.24 Buffer Overflow

    61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • java获取gps 串口_从串口读取GPS数据

    网上找来的代码自己修改之后放到这里的 参考地址 xff1a http www pcppc cn kaifa VBjiaocheng kaifa 18010 html http www itqoo com programme ASPNET 2
  • 串口转以太网服务器原理,串口服务器和串口转以太网模块的区别

    现在市面上的串口转以太网产品主要有两种 xff0c 即串口服务器和串口转以太网模块 用户在开始项目前 xff0c 首先需要考虑的是选择串口服务器还是串口转以太网模块 拓普瑞 TP305V1 0 USR TCP232 24 上图所示 xff0
  • 面向未来飞车应用的Kerloud Flyingrover开发平台

    简介 飞行汽车是经常在科幻文学 影视作品中出现的酷炫元素 xff0c 充斥着人们对未来的美好憧憬 随着Google Airbus等科技巨头加入研发阵营 xff0c 配合未来新的空中交通管制系统 xff0c 汽车飞上天终将成为现实 为了满足开
  • 【转载】深蓝学院-运动规划重点笔记

    原文链接 xff1a https blog csdn net wqwqqwqw1231 article details 107310965 基于图搜索的方法 配置空间 xff1a 维度等于机器人的自由度 xff0c 可以理解为一个点可以表示
  • cmake 指定 c++ 编译_CMake入门

    前言 自从 AndroidStudio2 2 开始支持 CMAKE 来构建 C C 43 43 程序之后 xff0c 作为 Android 开发就可以使用 CMake 来替换 Android mk 了 基本使用 在学习 CMAKE 之前 x
  • 蓝牙键盘连接——输入pin码

    台式机搭配苹果蓝牙键盘时 输入键盘PIN怎么办 xff1f 硬件背景 xff1a Win10 系统台式机 xff1b TP Link 蓝牙接收器 xff1b 苹果一代妙控蓝牙键盘 问题描述 xff1a 键盘初次连接时没有问题 xff0c 跟
  • PyCharm —— 缓存过多,系统盘释放(已解决)

    背景 pycharm安装过好多次 xff0c 每次安装之后 xff0c 就会自动加载数据集 xff0c 数据集31Gb xff0c 原本不大的系统盘直接存满 思路 在系统盘中 xff0c 有一个位置会缓存 pycharm 的数据 xff0c
  • macOS 10.15 支持的 xcode版本

    https xcodereleases com xcode11 3 1是macOS 10 14 6支持的最后一个版本 xff0c 从11 4开始 xff0c xcode就需macOS10 15 43 最新的XCode 12也是如此
  • 【PyTorch教程】P6-P7 数据加载

    完整目录 P6 P7 数据加载P8 9 Tensorboard使用P10 11 Transform的用法P12 13 常用的tranformsP14 torchvision中的数据集的使用P15 dataloader的使用P16 nn Mo
  • 【PyTorch教程】制作数据集的标签(label)

    关于制作数据集的label xff1a 在P7视频的最后 xff0c 写了这段 xff0c 用来重新命名文件的label的img 和 label 的管理方法 xff0c 有两种 xff1a 1 用img所在文件夹的名称 xff0c 作为la
  • 【PyTorch教程】pytorch入门系列 ——土堆教程的目录及索引

    一 几句题外话 深度学习上手已经很长时间了 xff0c 还记得最初的入门是跟着B站up小土堆的一步步学起来的 xff0c 从起初的环境配置 xff0c 到现在调整整个模型的进阶 xff0c 非常感谢土堆的贡献 写这个博客的初衷是为了自己看着
  • 【Pytorch深度学习实践】B站up刘二大人之 Gradient Descend-代码理解与实现(2/9)

    开篇几句题外话 xff1a 以往的代码 xff0c 都是随便看看就过去了 xff0c 没有这样较真过 xff0c 以至于看了很久的深度学习和Python xff0c 都没有能够形成编程能力 xff1b 这次算是废寝忘食的深入进去了 xff0
  • 【h5文件读取】h5文件读取——深度学习数据集常用

    数据集的常用格式 xff1a h5 深度学习搞了很长时间 xff0c 其中开源的代码中经常用到大型数据集 xff0c 里面的数据类型是h5格式 xff0c 这个格式困扰我挺长时间 xff0c 因为隔离还拿不到实验室的程序 xff0c 只好硬
  • Kerloud UAV室内光流定位教程

    产品简介 Kerloud UAV系列作为云讷科技 xff08 深圳 xff09 面向无人机系统集成爱好者的高性价比开发平台 xff0c 支持PX4 Dronecode ROS Nvidia和Ubuntu等高级软件社区 产品设计紧凑 xff0

随机推荐