精华内容
下载资源
问答
  • STM32外设
    2021-07-03 10:21:19

    1.认识

    STM32管脚40个,常见是整个最小系统板,具体介绍认识可自行百度

    在这里插入图片描述

    2.外设------------1.内部外设; 2.外设。

    内部是单片机里集成的功能,外设是指单片机扩展的功能

    官方回答:

    单片机内部的外设一般包括:串口控制模块,SPI模块,I2C模块,A/D模块,PWM模块,CAN模块,EEPROM,比较器模块,等等,它们都集成在单片机内部,有相对应的内部控制寄存器,可通过单片机指令直接控制。
    外设指的是单片机外部的外围功能模块,比如键盘控制芯片,液晶,A/D转换芯片,等等。外设可通过单片机的I/O,SPI,I2C等总线控制。

    3.如何选择外设IO口

    平时接到的外设都是ADC/SPI/PWM等,连接外设的时候,需要看清楚管脚的标识,如下图:

    1+.连接ADC外设,需要寻找管脚有没有ADC的字样,比如图中说的"ADC123"的字样,就是说明这个管脚内映射了ADC的三个通道,后边的IN0-15是说这个玩意有多少个。

    1++.解释完单片机上的ADC标识,如果要接ADC外设还绕不开三个东西-------

            上拉:使IO口接上拉电阻到VCC了,跟51一样
            下拉:使IO口接下拉电阻到GND了
            浮空:即不接上拉,也不接下拉,啥都不接,这样的话IO默认输入电平不确定
    

    悬空和高阻态的区别:

              悬空(浮空,floating):就是逻辑器件的输入引脚即不接高电平,也不接低电        平。由于逻辑器件的内部结构,当它输入引脚悬空时,相当于该引脚接了高电平。一般实际运用时,引脚不建议悬空,易受干扰。 
    
              高阻态:从逻辑器件内部电路结构来说,就是其输出电阻很大,该状态即不是高电平,也不是低电平。当三态门处于高阻态时,无论该门的输入如何变化,都不会对其输出有贡献。  
    

    (这里大体了解一下后边会更深一步应用讲解)

    总结:接入ADS外设,需要两个条件,一找到合适的标识管脚,二找到的表示管脚需是输入浮空。
    在这里插入图片描述
    2+.连接SPI外设,寻找管脚一样的先找标识,道理同上,不同的是SPI对浮空的把关轻松一点,片选(一条连接的线上有很多的路,你要人为给他卡一下关,告诉他电流和信息运输到哪里去,这就是我个人理解的片选,详细可以百度)的时候注意一下就好了

    3+.连接PWM外设,和ADC一样的,要求管脚和浮空

       补充:32单片机的一个管脚上可能有别的很多的功能注释,怎么选择就需要选择器的帮助了,再者到后边可以使用重映射(百度上解释的很详细,可以自行查看),到这里32的初步外设就搞定了!
    
    更多相关内容
  • 电子-STM32外设地址的设置.doc,单片机/嵌入式STM32-F0/F1/F2
  • STM32入门系列-STM32外设地址映射 片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB1挂载低速外设,APB2和AHB挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也...

    STM32入门系列-STM32外设地址映射

     

    片上外设区分为四条总线,根据外设速度的不同,不同总线挂载着不同的外设,APB1挂载低速外设,APB2和AHB挂载高速外设。相应总线的最低地址我们称为该总线的基地址,总线基地址也是挂载在该总线上的首个外设的地址。APB1总线的地址最低,因此片上外设就从这这个地址开始,也称外设基地址。

    总线基地址

        从存储器映射那张图的Block2可以看到,分为4大块,每块都有一个起始地址,这个起始地址就是基地址,然后到下一块起始地址的时候就会和前一块地址出现偏差,这个差值就是偏移量,即相对基地址的偏移量。如下图所示。

     

     

        从上图可以看到APB1总线基地址是0x4000 0000,相对外设基地址的偏移量是0,所以此总线也是外设Block2的基地址。

    外设基地址

        每条总线上都会挂接着很多的外设,这些外设也会有自己的地址范围,XXX 外设的首个地址即最低地址就是XXX外设的基地址,也称作XXX边界地址。有关STM32F1xx 外设的具体边界地址可以参考《STM32F1xx 中文参考手册》P28页, 里面有详细的介绍。 这里我们就以GPIO外设来讲解外设基地址。其他的外设也是同样分析。GPIO外设基地址如下图所示。

     

     

        从图中可以知道,外设GPIOx都是挂接在APB2总线上,属于高速的外设,而APB2总线的基地址是0x4001 0000,故GPIOA的相对APB2总线的地址偏移是800。

    外设寄存器地址

        XXX外设的寄存器就分布在其对应的外设地址范围内。这里我们以GPIO外设为例,GPIO是通用输入输出端口的简称,可以通过软件来控制其输入和输出。GPIO有很多个寄存器,每一个都有特定的功能。每个寄存器为32bit,占四个字节,这些寄存器都是按顺序依次排列在外设的基地址上。寄存器的位置都以相对该外设基地址的偏移地址来描述。这里我们以GPIOC端口为例,来说明GPIO都有哪些寄存器,如下图所示。

     

     

        这里就以GPIOC_BSRR寄存器来教大家如何看《STM32F1xx 中文参考手册》内寄存器的说明。 如果想要了解更多的寄存器内容, 可以参考《STM32F1xx中文参考手册》相应寄存器外设部分。首先我们需要打开参考手册,找到GPIO外设章节,里面会有一个GPIO寄存器,只要找到我们所要查找的寄存器即可,如下图所示。

     

     

        下面我们就对上图进行分析,带领大家这么获取其中的信息。

        A.红色框 4 表示的我们所查找寄存器的名称,寄存器GPIOx_BSRR内的x表示的是STM32GPIO端口,范围是A-E,也就是说在GPIOA、GPIOB等端口中都有这个寄存器。

        B.红色框5表示的是相对GPIOx地址的偏移值,比如现在我们使用的是GPIOC外设,其基地址是0x40011000,那么本寄存器GPIOx_BSRR地址=0x40011000+0x10=0x40011010。对于其他的GPIO外设也是一个原理。

        C.红色框6和7表示的是寄存器的位表。其中6表示寄存器编号,因为一个寄存器是32bit,所以范围是0-31。7表示的是相应位的权限,w:只写,r:只读,rw:可读可写。本寄存器位权限是w,所以只能写,如果试图读本寄存器,是无法保证读取到它真正内容的。而有的寄存器位权限为只读,一般是用于表示STM32 外设的某种工作状态的,由STM32硬件自动更改,通过读取那些寄存器位来判断外设的工作状态。

        D.红色框 8 是寄存器位功能说明。这个也是寄存器说明中最重要的部分,它详细介绍了寄存器每一个位的功能。例如本寄存器中有两种寄存器位,分别为BRy及BSy,其中的y数值表示的是管脚号,可以是0-15。如BR0、BS0用于控制GPIOx的第0个引脚,若 x 表示GPIOC,那就是控制GPIOC的第0引脚,而BR1、BS1就是控制GPIOC第1个引脚。

        其中BRy引脚的说明是“ 0:不会对相应的ODRx位执行任何操作;1:对相应ODRx位进行复位”。这里的“复位”是将该位设置为0的意思,而“置位”表示将该位设置为1;说明中的ODRx是另一个寄存器的寄存器位,我们只需要知道ODRx位为1的时候,对应的引脚x输出高电平,为0的时候对应的引脚输出低电平即可。感兴趣的可以查询该寄存器GPIOx_ODR的说明来了解。

        所以,如果对BR0写入“ 1”的话,那么GPIOx的第0个引脚就会输出“低电平”,但是对BR0写入“0”的话,却不会影响ODR0位,所以引脚电平不会改变。要想该引脚输出“高电平”,就需要对“BS0”位写入“1”,寄存器位BSy与BRy是相反的操作。

    展开全文
  • stm32外设总结-定时器使用

    千次阅读 2022-03-09 13:18:15
    文章目录1、stm32定时器资源概述2、使用定时器基本定时 1、stm32定时器资源概述 2、使用定时器基本定时


    本文用到的实验平台:

    • 野火MINI-stm32开发板
    • STM32CUBE-IDE开发工具

    1、stm32定时器资源概述

    关于定时器,野火《零死角玩转 STM32F103》一书中介绍如下,并用一张框图概括总结了stm32定时器的功能
    在这里插入图片描述
    基本上定时器都会有时基,要不怎么叫定时器呢,定时器的时钟框图如下所示
    在这里插入图片描述
    时钟源就是内部时钟,高级定时器挂载在APB1总线,基本和通用定时器都是挂载在APB2总线下的,不过最后经过一系列倍频什么的都是72Mhz,如下所示
    在这里插入图片描述
    经过时钟源后就进入了PSC预分频器,就是CK_CNT,CK_CNT用来驱动计数器计数。 PSC 是16 位的预分频器,可以对定时器时钟进行 1~65536 之间的任何一个数进行分频,具体计算方式为:CK_CNT=72Mhz/(PSC+1)

    再之后就进入计数器CNT,CNT也是16位的计数器,最大计数值为65535,当计数值达到自动重装载寄存器的时候就产生更新事件,并重新进行计数。当然自动重装载寄存器的值也是我们设置的,自动重装载寄存器ARR也是一个16位的寄存器,当计数值达到这个值的时候,就会产生更新事件,比如中断事件,触发其他外设的事件,或者复位计数器的事件。

    所以最终定时时间为:

    在这里插入图片描述
    以stm32的基本定时器6为例,打开配置页面就可以看到我们上面讲的一些寄存器了
    在这里插入图片描述

    2、使用定时器基本定时

    以定时器6为例,配置分频系数和自动重装载值
    在这里插入图片描述
    并开启中断
    在这里插入图片描述
    在初始化函数中开启定时器中断
    在这里插入图片描述
    编写中断回调函数

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	static uint32_t time = 0;
        if(htim==(&htim6))
        {
        	time++;
        	if(time == 1000) //1ms计数1000次就是1s
        	{
        		time = 0; //及时复位计数值
        		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
        	}
        }
    }
    

    将程序下载到开发板就能看到led一秒闪烁一次了!!!

    3、单脉冲模式来写延时函数

    我们在配置定时器的时候可以看到居然有这样一个选项,翻译下是单脉冲模式的意思
    在这里插入图片描述
    好家伙试了下要是用来做基本定时实验的时候这个功能千万不要勾选,不然的话就会一直亮着,就不会1s闪烁一次了
    在这里插入图片描述

    为啥呢,原来TIMx_CR1的OPM位

    位 3 OPM:单脉冲模式 (One-pulse mode)

    • 0:计数器在发生更新事件时不会停止计数
    • 1:计数器在发生下一更新事件时停止计数(将 CEN 位清零)

    在这里插入图片描述
    都不会停止计数了啊,那就只会发生一次中断了,那就肯定就没有1s的led亮灭了啊,但是根据这个特性我们就可以做延时函数了,嗯,确实不错!!!

    那要延时的话必然得整个us级别的吧,ms的他都有了还整啥,所以我们配一个us的计数

    在这里插入图片描述

    编写延时函数如下:

    void delay_us(uint32_t us)
    {
    	TIM6 -> ARR = us - 1;
    	TIM6 -> CR1 |= TIM_CR1_CEN;
    	while(TIM6->CR1&TIM_CR1_CEN);
    }
    

    之后在主函数中开启定时器

    在这里插入图片描述
    还是来写比肩方便的io翻转的函数
    在这里插入图片描述
    之后我们再用逻辑分析仪来测试读取
    在这里插入图片描述
    可以看到还是有点效果的hhh!!!

    us延时的方案再次加一

    4、外部时钟输入

    一般我们在使用定时器的时候常见的是内部时钟,但其实也可以外部,我们一般都直接忽略过去了,因此这里我做下介绍!
    在这里插入图片描述
    这里我们配置下这个时钟,配置信息如下所示

    在这里插入图片描述
    同时我们可以看到引脚上多了一个外部时钟输入引脚
    在这里插入图片描述
    同时我们开启下外部中断,方我们进行后续的中断处理
    在这里插入图片描述

    那么时钟是啥呢,我们最通俗的理解不就是方波吗,一段时间高一段时间低电平的这个样子,因此我们在软件中来产生一个方波,当然我们同样可以借用外部设备来实现这个功能,效果是一样的!!!

    下面正式开启代码部分的编写

    • 回调函数
      在这里插入图片描述
    • 产生时钟
      在这里插入图片描述
      硬件设备上做一下短接,这样就能看到现象了
      在这里插入图片描述
      根据我们之前的设计,不分频,十个周期进行一次中断,那就是1s一次中断了!!!

    同时我们回去看他的配置页面,关于分频系数这里,比如如果我们设置了分频,那么我们计数时间会变的更长,因为频率被分掉了,没有那么快了,这个可以和使用内部时钟的概念来看!
    在这里插入图片描述

    5、输入捕获测量频率和脉宽

    定时器具有输入捕获功能,可用于测量脉宽,频率等

    大致示意图如下所示
    在这里插入图片描述

    在cubemx中的配置如下所示:
    在这里插入图片描述
    其实他还是时基,然后根据上升沿下降沿来计数的一种方式,这里我用的最小计数周期为1us,然后最大计数值为65535,选择了上升沿捕获。
    在这里插入图片描述
    同时用另一个定时器来生成PWM,关于PWM配置的详细问题,下面的部分有专门的介绍
    在这里插入图片描述
    之后我们在初始化函数中开启捕获
    在这里插入图片描述
    具体代码如下所示

      __HAL_TIM_CLEAR_FLAG(&htim3,TIM_IT_UPDATE);
      HAL_TIM_Base_Start_IT(&htim3);
      HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
    
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
      __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,200);
    

    之后我们编写捕获完成回调函数,回调函数的位置如下图所示:
    在这里插入图片描述
    定义一个变量来获取捕获值
    在这里插入图片描述
    之后我们进入调试查看,我们这个代码比较简陋,因此我们只坐一次捕获试试效果!
    在这里插入图片描述
    运行程序,可以看到程序暂停在断点处,同时查看变量情况如下
    在这里插入图片描述
    我们在查看下逻辑分析仪结果,两次上升沿之间时间间隔为1000us左右,基本是没问题的!
    在这里插入图片描述
    那下面我们开始完善代码,让他可以连续读取,并处理脉宽什么的了,简单而言就是捕获到上升研的时候设置下降沿捕获,捕获到下降沿的时候设置为上升沿捕获,这样就行了

    以测量一个按键的高低电平时间为例:

    从原理图上查到按键的位置为PA1
    在这里插入图片描述
    设置为输入模式,最长记录时间65536us

    在这里插入图片描述
    这里我们开启中断用于计数
    在这里插入图片描述

    下面开始编写代码

    事先准备好需要的变量
    在这里插入图片描述

    uint32_t ccr_cnt,period_cnt;
    uint8_t tri_flag,end_flag;
    uint32_t cnt_cl=72000000/72;;
    float time;
    

    计数部分代码如下
    在这里插入图片描述

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	period_cnt++;//中断计数
    }
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    	if(tri_flag==0)
    	{
    		period_cnt=0;//中断次数清零
    		__HAL_TIM_SET_COUNTER(&htim2,0); 
    		ccr_cnt=0;
    		__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);
    		tri_flag=1;
    	}
    	else
    	{
    		ccr_cnt=__HAL_TIM_GET_COMPARE(&htim2, TIM_CHANNEL_1);
    		//ccr_cnt=HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//功能同上
    		__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
    		tri_flag=0;
    		end_flag=1;//捕获完成标志
    	}
    }
    

    下面在主函数里编写函数读取
    在这里插入图片描述

    	  	if(end_flag==1)//结束捕获
    	  	{
    	  		time=(float)(period_cnt*1000+(ccr_cnt+1))/cnt_cl;//结果强制转换为浮点型
    	  		printf( "\r\n测得高电平脉宽时间:%.3fs\r\n",time);//输出结果保留小数点后两位
    	  		end_flag=0;
    	  	}
    

    下载到开发板,按下按键,可以看到结果如下,测试正常!
    在这里插入图片描述

    下面我们来读取频率和脉宽,我们用一个定时器生成PWM,用另一组定时器的输入捕获通道来读取他的数值

    TIM2产生PWM
    在这里插入图片描述
    TIM3输入捕获
    在这里插入图片描述

    首先还是设置相关标志位

    #define cnt_clk 72000000/(71+1)
    #define arr 65535 //最大计数周期
    uint32_t ccr_cnt1,ccr_cnt2;
    uint32_t Period_cnt,Period_cnt1,Period_cnt2;
    uint32_t ic_flag,end_flag;
    float duty_cycle,frequency; //记录频率和脉宽
    

    中断函数处理如下
    在这里插入图片描述
    完整代码如下:

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	Period_cnt++;
    }
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    	switch(ic_flag)
    	{
    		case 0://第一个上升沿捕获
    		{
    			__HAL_TIM_SET_COUNTER(&htim3,0);
    			ccr_cnt1=0;
    			ccr_cnt2=0;
    			Period_cnt=0;
    			Period_cnt1=0;
    			Period_cnt2=0;
    			__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING); 
    			ic_flag=1;
    			break;
    		}
    		case 1://第一个下降沿捕获
    		{
    			ccr_cnt1=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);
    			Period_cnt1=Period_cnt;
    			__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);	
    			ic_flag=2;	
    			break;
    		}
    		case 2://第二个上升沿捕获
    		{
    			ccr_cnt2=__HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);
    			Period_cnt2=Period_cnt;
    			ic_flag=0;	
    			end_flag=1;
    			break;
    		}
    		default:
    		break;
    	}
    }
    

    最终的输出代码如下所示
    在这里插入图片描述
    源代码如下,因为PWM的速度比较快,所以建议还是加个延时函数比较好

    	  	if(end_flag==1)
    	  	{
    	  		duty_cycle=(float)(Period_cnt1*(arr+1)+ccr_cnt1+1)*100/(Period_cnt2*(arr+1)+ccr_cnt2+1);
    	  		frequency=(float)cnt_clk/(Period_cnt2*(arr+1)+ccr_cnt2+1);
    	  		printf("频率%.2f,占空比%.2f\r\n",frequency,duty_cycle);
    	  		end_flag=0;
    	  	}
    		HAL_Delay(1000);
    

    下载到开发板,打印结果如下所示:
    在这里插入图片描述

    6、PWM输入

    上面我们用的是软件的方式进行的测量脉宽,但是同样的我们可以用硬件的方式,这个在野火的教程中讲的较为详细
    在这里插入图片描述
    具体介绍如下
    在这里插入图片描述
    PWM 信号由输入通道 TI1 进入,因为是 PWM 输入模式的缘故,信号会被分为两路,一路是 TI1FP1,另外一路是 TI2FP2。其中一路是周期,另一路是占空比,具体哪一路信号对应周期还是占空比,得从程序上设置哪一路信号作为触发输入,作为触发输入的哪一路信号对应的就是周期,另一路就是对应占空比。作为触发输入的那一路信号还需要设置极性,是上升沿还是下降沿捕获,一旦设置好触发输入的极性,另外一路硬件就会自动配置为相反的极性捕获,无需软件配置。一句话概括就是:选定输入通道,确定触发信号,然后设置触发信号的极性即可,因为是 PWM 输入的缘故,另一路信号则由硬件配置,无需软件配置。

    同时注意:使用 PWM 输入模式的时候必须将从模式控制器配置为复位模式,这个在我们下面的配置中将体现出来

    PWM输入模式时序如下所示:
    在这里插入图片描述
    测量原理为:PWM 信号由输入通道 TI1 进入,配置 TI1FP1 为触发信号,上升沿捕获。当上升沿的时候 IC1 和 IC2 同时捕获,计数器 CNT 清零,到了下降沿的时候, IC2 捕获,此时计数器CNT 的值被锁存到捕获寄存器 CCR2 中,到了下一个上升沿的时候, IC1 捕获,计数器CNT 的值被锁存到捕获寄存器 CCR1 中。其中 CCR2+1 测量的是脉宽, CCR1+1 测量的是周期。 这里要注意的是 CCR2 和 CCR1 的值在计算占空比和频率的时候都必须加 1, 因为计数器是从 0 开始计数的。

    在cubemx中配置如下所示:

    可以看到两个通道其实是共用一个引脚的
    在这里插入图片描述
    编写输入捕获部分代码如下所示
    在这里插入图片描述
    源代码

    uint32_t Cap_val1,Cap_val2;
    float Duty,Frequency;
    
    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
    {
    	Cap_val1 = HAL_TIM_ReadCapturedValue (&htim3 ,TIM_CHANNEL_1 );
    	Cap_val2 = HAL_TIM_ReadCapturedValue (&htim3 ,TIM_CHANNEL_2 );
    	if(Cap_val1 != 0)
    	{
    		Duty = (float )(Cap_val2+ 1)*100 / (Cap_val1 +1) ;
    		Frequency = 72000000 / 72 / (float )(Cap_val1 +1) ;
    	}
    }
    
    

    在主函数中编写读取代码
    在这里插入图片描述
    将程序下载到开发板,可以看到效果如下,非常准确
    在这里插入图片描述
    既准确又方便,但是牺牲了一个定时器,看来也不全是好事啊哈哈哈!!!

    7、PWM输出

    PWM是我们经常要用到的外设,在电机控制等方面有很广泛的应用

    百度百科上的解释如下所示 :PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。

    通俗点一句话就是:PWM是数字量(01两种状态),PWM常用于模拟,任何模拟值都可以用PWM进行编码

    一般我们在配置PWM的常用操作如下所示:

    选择为PWM输出模式
    在这里插入图片描述
    设置时基等基本参数,之后配置通道
    在这里插入图片描述
    编写代码如下所示

      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //开启pwm通道
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
      HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
    
      __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,200); // 设置tim输出值
      __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,400);
      __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,600);
      __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_4,800);
    

    使用逻辑分析仪查看值,关于这里的计算,可以参考上面讲到的基本定时器时基配置,基本差不多,区别就在与当计数值达到CCR的时候被截断了!
    在这里插入图片描述
    这样我们就能看到pwm比较完整的状态了,下面我对刚才讲到的一些参数进行说明:

    • PWM模式

    stm32有两种pwm模式:

    模式CNT计数方式说明
    PWM1递增CNT<CCR,通道有效
    PWM1递减CNT>CCR,通道有效
    PWM2递增CNT>CCR,通道有效
    PWM2递减CNT<CCR,通道有效

    简单来说就是如果其他参数相同,PWM1和PWM2模式输出的PWM是互补的!

    • 极性

    上面讲到了通道有效,那么通道有效是高电平还是低电平呢,这个就是极性,就是极性选择高通道有效时候输出的就是高电平,反之输出的是低电平!

    • Pulse

    这个其实就是初始设置的CCR值了,默认情况下是0,我们如果想上电就输出PWM,那就要事先给他设置好相应的值,当然你也可以就是在初始化中使用软件设置!

    软件设置的代码如下:

    首先开启定时器PWM输出

     HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
    

    设置比较值

    __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,200);
    
    • fast_mode

    暂时还不清楚

    8、PWM输出的一些模式

    • 对齐模式,这个好像不是PWM独有的,因为他是一种计数模式,定时器的一些功能应该都有的,我们点开定时器的这个计数模式查看如下:可以看到除了向上向下计数还有几种模式可以选的
      在这里插入图片描述
      这其实就是对齐模式,分别为左对齐,右对齐,中心对齐,左右对齐可以统一称为边缘对齐模式,其实也很好理解,pwm不是输出01吗,然后就是计数过程中达到一个值就会突变,就是怎么去靠近这个值得方法呗,用同样的一条水平线去截取下面的图像都会有不同的结果!

    9、PWM互补输出

    顾名思义,互补的PWM就是互相补充嘛,就是PWM之间相互补充输入,一个输出高的时候另一边就输出低电平

    在cubemx中配置互补输出如下所示:
    在这里插入图片描述
    启动代码也要做相应修改,添加互补输出的PWM开启函数:
    在这里插入图片描述
    将程序下载到开发板并接上逻辑分析仪效果如下所示
    在这里插入图片描述
    当然在互补中我们还看到有刹车和死区的部分,其实死区是一直存在的,只是时间比较短,因为这是硬件的伤
    在这里插入图片描述
    野火教程解释如下:在这个半桥驱动电路中, Q1 导通, Q2 截止,此时我想让 Q1 截止 Q2 导通,肯定是要先让Q1 截止一段时间之后,再等一段时间才让 Q2 导通,那么这段等待的时间就称为死区时间,因为 Q1 关闭需要时间(由 MOS 管的工艺决定)。如果 Q1 关闭之后,马上打开 Q2,那么此时一段时间内相当于 Q1 和 Q2 都导通了,这样电路会短路。

    关于死区时间的计算我在下面的图中已经注明,为了较明显的看到死区的效果,我这里增大频率,同时设置一个相对较大的死区时间

    在这里插入图片描述
    将程序下载到开发板可以看到效果如下所示:

    在这里插入图片描述

    10、编码器模式

    关于编码器模式我在之前的一篇文章中有讲到过 直流编码电机双闭环(速度+角度)控制

    这里仅仅是为了让整个体系更完善一点,加入了这个部分,详情可以看那篇文章的介绍!

    cube中的配置如下
    在这里插入图片描述
    这里编码器模式可以选T1,T2,T12三种模式
    在这里插入图片描述
    详情还是看那篇文章吧!

    11、基于定时器的伪系统

    因为系统就是时间的调度吗,所以我们就可以用一个硬件定时器衍生出很多不同的软件定时器(假的),大致思路如下:

    首先产生一个1ms周期的中断

    在这里插入图片描述
    之后我们编写回调函数,利用一个变量的判断实现不同阶段的延时,在延时里面可以设置周期任务之类的,同时在最终将这个变量清零,并翻转led,led的闪烁状况就可以作为系统运行的标志!
    在这里插入图片描述
    源码如下所示:

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    {
    	static uint32_t time = 0;
        if(htim==(&htim6))
        {
        	time++;
        	if(time % 2 == 0) // 2ms的周期任务
        	{
        		// xxx		
        	}
        	if(time % 5 == 0) // 5ms的周期任务
        	{
        		// xxx		
        	}
        	if(time % 10 == 0) // 10ms的周期任务
        	{
        		// xxx		
        	}
        	if(time == 1000) //1ms计数1000次就是1s
        	{
        		time = 0; //及时复位计数值
        		HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); //用作系统运行指示灯
        	}
        }
    }
    

    12、更多!!!

    定时器可以算是stm32非常重要的外设了,我这篇也仅仅是部分的记录,还有比如无刷电机控制相关的,一些工业应用诸如刹车,死区等都没有讲或者很详细的介绍,希望以后都能一一接触到,并继续分享!!!

    展开全文
  • STM32常用外设驱动程序
  • 这篇文档是为提供STM32F10xxx CAN外设使用的应用程序
  • STM32外设库.zip

    2020-09-13 13:10:31
    STM32F10X系列外设驱动固件库,其包含了典型STM32F10X系列外设驱动。其版本为STM32F10x_StdPerph_Lib_V3.5.0。
  • STM32学习笔记NO1. STM32外设使用总结

    千次阅读 2019-02-01 12:24:15
    目录 一.各种输入输出模式 1.1 输入模式 1.2 输出模式 2.输出频率设置 2.1 如何选择输出频率 二、时钟源 1.1各个时钟源作用 三、存储器 ...五、STM32硬件IIC高级库调用,解决硬件IIC b...

    目录

    一.各种输入输出模式

    1.1 输入模式

    1.2 输出模式

    2.输出频率设置

    2.1 如何选择输出频率

    二、时钟源

    1.1各个时钟源作用

     

    三、存储器

    1.SRAM

    2.存储器结构

    3.Program Size: Code=x RO-data=x RW-data=x ZI-data=x 的含义

    四、中断与事件

    五、STM32硬件IIC高级库调用,解决硬件IIC busy等问题


     

    一.各种输入输出模式

    1.1 输入模式

    • 模拟输入 GPIO_AIN:应用ADC模拟输入,或者低功耗下省电
    • 浮空输入 GPIO_IN_FLOATING:引脚处于浮空模式,电平状态是不确定的。外部信号输入什么,IO口就是什么状态。
    • 上拉输入 GPIO_IPU:防止IO口出现不确定的状态,比如,当IO口悬空时,就会通过内部的上拉电阻将该点钳位在高电平
    • 下拉输入 GPIO_IPD:功能与上拉电阻类似,防止IO口出现不确定的状态,比如,当IO口悬空时,就会通过内部的下拉电阻将该点钳位在低电平

    注:

    • IO端口复位后处于浮空状态,也就是其电平状态由外围电路决定
    • STM32上电复位瞬间I/O口的电平状态默认是浮空输入,因此是高阻。做到低功耗
    • STM32的IO管脚配置口默认为浮空输入,把选择权留给用户,这是一个很大的优势:一方面浮空输入确保不会出现用户不希望的默认电平(此时电平取决于用户的外围电路);另一方面降低了功耗,因为不管是上拉还是下拉都会有电流消耗。从另一个角度来看,不管I/O管脚的默认配置如何,还是需要在输出的管脚外加上拉或下拉,这是为了保证芯片上电期间和复位时输出的管脚始终处于已知的电平
    • 关于模拟输入&低功耗,根据STM32的低功耗AN(AN2629)及其源文件,在STOP模式下,为了得到尽量低的功耗,确实把所有的IO(包括非A/D输入的GPIO)都设置为模拟输入

    1.2 输出模式

    • 开漏输出GPIO_OUT_ODIO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变 。可以读IO输入电平变化,实现C51的IO双向功能
    • 推挽输出GPIO_OUT_PP  :IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
    • 复用功能的推挽输出GPIO_AF_PP  :一般设置片内外设功能(I2C的SCL,SDA)
    • 复用功能的开漏输出GPIO_AF_OD : 片内外设功能(TX1,MOSI,MISO.SCK.SS)

    注:

    • 在没有任何操作的情况下,STM32通用推挽输出模式的引脚默认低电平,也就是有电的状态。所以在配置的时候通常会先把引脚的电平设置拉高,让电路不产生电流。有电到没电这一过程也就是引脚电平从低到高的过程。
    • 模拟I2C使用开漏输出GPIO_OUT_OD,接上拉电阻,能够正确输出0和1;读值时先GPIO_SetBits(GPIOB, GPIO_Pin_0);拉高,然后可以读IO的值;使用GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0);如果是无上拉电阻,IO默认是高电平;需要读取IO的值,可以使用带上拉输入_IPU和浮空输入GPIO_IN_FLOATING和 开漏输出GPIO_OUT_OD;
    • 推挽输出:推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止。可以输出高,低电平,连接数字器件;
    • 开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)

    2.输出频率设置

            STM32的GPIO有3种输出速度(2MHz、10MHz和50MHz),这个速度是指I/O口驱动电路的响应速度。通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。高频的驱动电路,噪声也高,当不需要高的输出频率时,请选用低频驱动电路,这样非常有利于提高系统的EMI性能。当然如果要输出较高频率的信号,但却选用了较低频率的驱动模块,很可能会得到失真的输出信号。

    2.1 如何选择输出频率

    输出频率一般是应用频率的10倍为宜,例如:

    • 对于串口,假如波特率115200,只需115.2k,那么用2M的GPIO的引脚速度就够了,既低功耗也噪声小
    • 对于I2C接口,假如使用400k波特率,若想把余量留大些,那么用2M的GPIO的引脚速度或许不够,这时可以选用10M的GPIO引脚速度
    • 对于SPI接口,假如使用18M或9M波特率,用10M的GPIO的引脚速度显然不够了,需要选用50M的GPIO的引脚速度

     

    二、时钟源

    1.1各个时钟源作用

    STM32有5个时钟源HSI、HSE、LSI、LSE、PLL,其实它只有四个,PLL是由HSI或HSE提供的。

    • 高速外部时钟(HSE):以外部晶振作时钟源,晶振频率可取范围为4~16MHz,我们一般采用8MHz的晶振
    • 高速内部时钟(HSI): 由内部RC振荡器产生,频率为8MHz,但不稳定
    • 低速外部时钟(LSE):以外部晶振作时钟源,主要提供给实时时钟模块,所以一般采用32.768KHz
    • 低速内部时钟(LSI):由内部RC振荡器产生,也主要提供给实时时钟模块,频率大约为40KHz

     

    三、存储器

    1.SRAM

    不同类型的STM32单片机的SRAM大小是不一样的,但是他们的起始地址都是0x2000 0000,终止地址都是0x2000 0000+其固定的容量大小。其作用是用来存取各种动态的输入输出数据、中间计算结果以及与外部存储器交换的数据和暂存数据。设备断电后,SRAM中存储的数据就会丢失。

    注:Cache 就是为了缓解低速存储器而设计的. STM32的数据通常在 SRAM 中, 是零等待的, 不需要缓存. 所以 STM32 的缓存技术只是针对 FLASH 的指令缓存.

    2.存储器结构

                                         

    其中:

    • Peripherals:外设的存储器映射,对该区域操作,就是对相应的外设进行操作;
    • SRAM:运行时临时存放代码的地方;
    • Flash:存放代码的地方;
    • System Memory:STM32出厂时自带的你只能使用,不能写或擦除
    • Option Bytes:可以按照用户的需要进行配置(如配置看门狗为硬件实现还是软件实现)

     

    3.Program Size: Code=x RO-data=x RW-data=x ZI-data=x 的含义

     

    四、中断与事件

     

    这张图是一条外部中断线或外部事件线的示意图,图中信号线上划有一条斜线,旁边标志19字样的注释,表示这样的线路共有19套。图中的蓝色虚线箭头,标出了外部中断信号的传输路径。图中红色虚线箭头,标出了外部事件信号的传输路径。

    简单举例:外部I/O触发AD转换,来测量外部物品的重量;如果使用传统的中断通道,需要I/O触发产生外部中断,外部中断服务程序启动AD转换,AD转换完成中断服务程序提交最后结果;要是使用事件通道,I/O触发产生事件,然后联动触发AD转换,AD转换完成中断服务程序提交最后结果;相比之下,后者不要软件参与AD触发,并且响应速度也更块;要是使用事件触发DMA操作,就完全不用软件参与就可以完成某些联动任务了。(引用:http://www.eeworld.com.cn/mcu/2015/1009/article_22780.html

     

    五、STM32硬件IIC高级库调用,解决硬件IIC busy等问题

    参考文档:https://www.docin.com/p-547338408.html

     

     

     

     

     

     

     

     

     

    展开全文
  • 电子-stm32外设固件库V3.0.0和新建工程模板.rar,单片机/嵌入式STM32-F0/F1/F2
  • STM32外设有哪些?外设在总线上是怎么挂载的?

    万次阅读 多人点赞 2018-03-30 17:21:37
    外设STM32库文件的下面路径下:(STM32库:stm32f10x_stdperiph_lib)stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver1.MISC:把NVIC的外设驱动放在了misc.c中...
  • STM32外设固件库

    2018-04-29 15:16:24
    资源都是来自官方文件的,目前是最新版,可以放心下载。
  • STM32_内核外设_CAN

    2021-01-06 06:03:51
    CAN构成STM32F1内核外设CAN的构成CAN的数据帧图示讲解控制/状态配置寄存器CAN_MCR寄存器CAN_BTR测试模式讲解位时序及波特率发送邮箱发送报文的流程寄存器接收FIFO验收筛选器筛选器分类按长度分类按模式分类标识符...
  • STM32外设初始化C语言代码(SPI、UART、TIME、CLOCK)。
  • STM32 的中文使用手册 包括107. 和外设库参考程序 。
  • STM32外设初始化步骤

    千次阅读 2019-09-22 13:22:23
    1、定义外设结构体; 2、开启外设时钟; 3、调用缺省值配置函数; 4、外设具体配置; 5、外设使能。 转载于:https://www.cnblogs.com/Chuck-Yue/p/10159511.html...
  • STM32F103外设库函数V3.5

    2015-12-29 15:30:42
    官方的STM32F103外设库函数V3.5,很好的参考资料,共有需要的兄弟姐妹下载使用。
  • STM32外设驱动_串口_PWM_定时器_矩阵.rar
  • STM32软件开发,由官方提供的标准库函数手册,详细介绍使用每个外设接口时程序设置的步骤,需要用到的函数,并给出每个函数的详细说明。 是软件开发必备文档
  • 串口DMA空闲接收,usb等
  • stm32 外设使用的配置步骤

    千次阅读 2018-05-10 17:21:00
    使用外设的配置步骤  #1 打开时钟  > 打开外设时钟  > 打开相关GPIO时钟  > 打开DMA时钟 (若需要) #2 关联外设与GPIO  > 复位关联GPIO时钟,进入复位--->退出复位  > 配置...
  • 看了许多资料都没有讲如何配置DMA通道外设基地址 ...#define ADC1_DR_Address ((u32)0x4001244C) 就是ADC1的外设基地址(0x4001 2400)加上ADC数据寄存器(ADC_DR)的偏移地址(0x4c)计算得到的。
  • STM32外设都有以下几类寄存器:
  • 电子-STM32通信外设应用级库函数.pdf,单片机/嵌入式STM32-F0/F1/F2
  • stm32外设的使能,失能,复位的区别

    千次阅读 2019-02-15 12:48:25
    首先明确的是,在STM32中所有外设正常工作的前提是使能了相应的外设,有的可能只用使能一个(如GPIO),有的使能两个(如GPIO和USART),有的可能需要使能三个(如GPIO,AIFO,TIM)。总而言之,只有使能了外设时钟外设...
  • STM32基础和常见外设

    2021-10-29 19:57:31
    STM32 开发环境 安装MDK软件 在桌面创建一个用于专门保存是stm32 的文件夹 安装芯片包 打开软件新建工程(Project)保存到文件夹 将启动文件添加到文件夹 点亮LED灯 配置使能APB2的GPIOC时钟 *(unsigned int *)...
  • STM32基本外设学习

    千次阅读 多人点赞 2019-09-29 19:52:50
    十月一回家没有网,弄了一下107开发板的基本外设,重新巩固一下知识点,所谓基础不牢地动山摇。一定要学好基础,然后在深入更多的知识的时候才会得心应手,不要不信我说的,我以前也是这样想,结果你们也都看见了,...
  • CH32F103常用外设stm32兼容性测评 1、测试CH32F103替换成stm32F103,常用外设程序兼容性实验 因为CH32F103系列最大flash只有64k,对标的是Stm32F103中等容量的单片机。但是CH32F103的flash扇区只有1K,所以需要...
  • STM32使用DMA功能使串口发送数据的同时,LED灯不停的闪烁
  • 偶然间论坛看到大牛分享的 STM32H743IIT6使用STM32CUBEMX配置大多数外设手册,在这里分享给大家。共同进步

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,474
精华内容 12,589
关键字:

stm32外设