tag 标签: stm32

相关博文
  • 热度 4
    2020-8-29 08:30
    706 次阅读|
    1 个评论
    使用 timer 产生脉冲波形,控制步进电机转动。当使用微步方式时,脉冲频率等于整步频率乘以细分数。有时,我们需要每步进行处理,也就是在发出脉冲时,产生中断。对于常用的双极步进电机,最快的速度大概是 2000PPS ,也就是一秒钟 10 圈。如果使用 256 细分,则输出脉冲频率为 512K ,这么高频率的中断,显然有问题。 有个方法,可以降低中断数量。 可以使用两个 TIMER ,其中一个用于产生电机控制脉冲。常规的办法是使用 50% 点空比的 PWM 脉冲。 使用两个 TIMER ,其中一个设置为 PWM 输出,另外不个设置为 PWM 无输出 void MOT_StartPPS(uint16_t para){ uint16_t temp; PSC = 99; temp = 0xFFFF ; ARR = temp - 1; CCR2 = temp / 2; PSC = 256*100-1; temp = 0xFFFF; ARR = temp - 1; CCR1 = temp / 2; 。。。。。。 HAL_TIM_PWM_Start(&htim15,TIM_CHANNEL_2); HAL_TIM_PWM_Start_IT(&htim16,TIM_CHANNEL_1); } 对于较高的速度,需要斜坡启动,所以将 PWM 脉冲重复频率设置为最慢,启动 PWM 输出,同时启动另一个 TIMER 的中断输出(这里我们只要中断,不要输出)。 随后在程序中,定时运行步述代码,逐步将频率提高,直到达到设定值。 if(ppsstart == 1){ if((mscnt % SLOPINT)==0){ ppsratenow += SLOPINCPPS; if(ppsratenow < ppsrate){ temprate = ppsratenow; } else{ temprate = ppsrate; ppsstart = 0; ppsratenow = 0; } PSC = 50/temprate; temp = (48000000 / 256) / temprate / (50/temprate + 1) ; ARR = temp - 1; //48000000 / 51200 * para / (para / 100 +1); //para 秒 / 圈 频率 = SYSCLK / ( 256 * para) CCR2 = temp / 2; PSC = 256*(50/temprate + 1)-1; temp = (48000000 / 256) / temprate / (50/temprate + 1) ; ARR = temp - 1; CCR1 = temp / 2; 两个 TIMER 计数时钟是相同的,所以产生的脉冲是同相位的。但因为其中一个预先分频要慢细分数,所以产生中断的速度等于步进电机整步速度。这样中断的速度就降低了细分倍。如果对步数精度要求不高,可以将预分频倍数进一步提高,这样可以让电机转数步,才产生一个中断。
  • 热度 2
    2020-8-7 16:26
    482 次阅读|
    0 个评论
    使用一个空闲不用的定时器,做如下设置,预分频设为0, 周期设置为 55520-1 /* TIM7 init function */ static void MX_TIM7_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; htim7.Instance = TIM7; htim7.Init.Prescaler = 0; htim7.Init.CounterMode = TIM_COUNTERMODE_UP; htim7.Init.Period = 65519; htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim7) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } 另外编写一个 delay_us的函数 /* 最大us数为 1356us */ inline void Delay_us(uint16_t us){ CNT = 0; HAL_TIM_Base_Start(&htim7); CNT < ((uint16_t)48 * us - 1)); } 调用时,将定时计数器清零,然后启动定时器,等待计数器达到设定的值后返回。 这里的时钟频率 PCLK为48M,计数器设定值为 48*us数。使用时注意这个数不要超过在period中的设定值。
  • 热度 1
    2020-7-23 16:20
    121 次阅读|
    0 个评论
    转载自 https://www.cnblogs.com/qiyuexin/p/8921718.html 目录 FAULTMASK PRIMASK BASEPRI BASEPRI_MAX 正文 1、总开关 每个CPU有一个中断总开关。通过CPU中断控制寄存器实现。Cortex-M的中断控制寄存器包括:FAULTMASK、PRIMASK、BASEPRI、BASEPRI_MAX。总开关的本质是变更当前执行优先级,根据Cortex-M的架构设计,只有优先级高于当前执行优先级的中断或异常才能抢占CPU。 回到顶部 FAULTMASK 设置为1后关闭所有中断和异常,包括HardFault异常,只有NMI和Reset可以得到响应。 回到顶部 PRIMASK 设置为1后关闭所有中断和除了HardFault异常外的所有其他异常,只有NMI、Reset和HardFault可以得到响应。 回到顶部 BASEPRI 设置为n后,屏蔽所有优先级数值大于等于n的中断和异常。Cortex-M的优先级数值越大其优先级越低。 回到顶部 BASEPRI_MAX 和BASEPRI类似,但有个限制,即后写入的优先级数值要比当前的BASEPRI值小才会起作用,否则不起作用。影响范围最广,影响CPU内的所有中断源。 事实上BASEPRI_MAX和BASSEPRI是操作同一个寄存器,不过BASEPRI_MAX是一个条件写指令,可以通过下列等效功能代码理解: // atomic related functions for unittest. extern uint8_t atomic_BASEPRI; // 用来模拟 BASEPRI 的值 // BASEPRI 设置 static inline uint8_t __set_BASEPRI(uint8_t prio) { atomic_BASEPRI = prio; } // BASEPRI_MAX 设置 static inline uint8_t __set_BASEPRI_MAX(uint8_t prio) { prio)) { atomic_BASEPRI = prio; } } 疑问:线程模式下,当前优先级和中断优先级的抢占优先级相同,但中断的子优先级比当前子优先级高,会怎么样?当前优先级也分抢占优先级和子优先级吗? 2、分开关 Cortex-M包括一个嵌套向量中断控制器NVIC,每个外设在NVIC中都有一个对应的位,用来控制该外设的中断。 ISER寄存器中外设对应位为1打开中断。 ICER寄存器中外设对应位为1关闭中断。 分开关只影响特定外设的中断。 3、源开关 外设通常有多个中断源,如接收到数据、发送完成、接收超时等等。外设通常提供中断使能寄存器控制哪些中断源产生时要向上汇报(向分开关汇报)。源开关与特定的外设相关,不同的外设会有不同的中断,有不同的中断控制寄存器。有些外设本身有总开关,该总开关控制该外设的所有中断。 源开关影响范围最窄,仅影响外设的某一种中断源。
  • 2020-7-5 14:42
    574 次阅读|
    0 个评论
    【不用开发板学习STM32】一般流水灯实验(文末获取代码及工程文件)
    • 实验环境 本次实验是通过Proteus+MDK一起模拟完成的。Proteus模拟实际电路,MDK编译代码。Proteus版本是8.9,MDK版本是5.21。需要注意的是,Proteus需要安装8.8以上版本,器件库里面要支持STM32F103C6。 • 实验目的 通过点亮三个LED,我们俗称的流水灯,来了解STM32的GPIO是怎么配置的。我们实验设置了Systick,即系统滴答时钟,延时也是通过这个滴答时钟来配置的,可以通过这个实验学习一下,怎么配置Systick,以及Systick中断怎么用。 • 主控: STM32F103C6(本来想用C8的,但是Proteus只有C6,本质上只有Flash和SRAM大小的区别,所有没有必要纠结) • 时钟: 没有用外部晶振,因为Proteus只支持一种时钟树,所以这里采用内部晶振,做实验够了。 • 复位电路: 复位电路如图,包含了上电复位电路一个10K电阻(图上用的是100K实际应该都是可以的)+一个100nF电容。按键复位电路,包含了一个自复位按键,按下后,RST管脚就会短路到GND,MCU就会复位。 • IO说明: 我们利用PA1、PA2、PA3来分别控制3个LED灯,输出低电平的时候,LED灯点亮。 • 代码目录概述: APP文件夹:主要包含应用函数的.C文件。 BSP文件夹:主要包含底层硬件驱动的.C文件。 MDK-ARM文件夹:主要包含STM32的启动的.S文件。 StdPeriph_Driver文件夹:主要包含ST官方提供的标准外设驱动.C文件(不是HAL库哦)。 CMSIS文件夹:系统内核配置文件,标准库自带的。 • 代码内容概述: ↓↓↓ GPIO初始化,先打开GPIOA的时钟,然后把PA1、PA2、PA3设置成推挽输出,代码如下: GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = LED1_Pin | LED2_Pin | LED3_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); ↓↓↓ Systick也要初始化,这里滴答时钟设置成1ms进一次中断,代码如下: void bsp_InitSysTick(void) { if (SysTick_Config(SystemCoreClock / 1000)) { /* Capture error */ while (1); } } ↓↓↓这里我们使用的是内部时钟,所以在初始化外设后还要把MCU设置成使用内部时钟,代码如下: void RCC_Configuration(void) { RCC_DeInit(); RCC_HSICmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div2); RCC_PCLK2Config(RCC_HCLK_Div1); RCC_ADCCLKConfig(RCC_PCLK2_Div4); RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_10); RCC_PLLCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); while(RCC_GetSYSCLKSource() != 0x08); } ↓↓↓ 更详细代码及工程文件,关注回复编号2001就能获取!!
  • 热度 2
    2020-7-1 10:24
    397 次阅读|
    0 个评论
    (转载)STM32之中断与事件---中断与事件的区别
    这张图是一条外部中断线或外部事件线的示意图,图中信号线上划有一条斜线,旁边标志19字样的注释,表示这样的线路共有19套.图中的蓝色虚线箭头,标出了外部中断信号的传输路径,首先外部信号从编号1的芯片管脚进入,经过编号2的边沿检测电路,通过编号3的或门进入中断挂起请求寄存器,最后经过编号4的与门输出到NVIC中断检测电路,这个边沿检测电路受上升沿或下降沿选择寄存器控制,用户可以使用这两个寄存器控制需要哪一个边沿产生中断,因为选择上升沿或下降沿是分别受2个平行的寄存器控制,所以用户可以同时选择上升沿或下降沿,而如果只有一个寄存器控制,那么只能选择一个边沿了. 按下来是编号3的或门,这个或门的另一个输入是软件中断/事件寄存器,从这里可以看出,软件可以优先于外部信号请求一个中断或事件,即当软件中断/事件寄存器的对应位为"1"时,不管外部信号如何,编号3的或门都会输出有效信号. 一个中断或事件请求信号经过编号3的或门后,进入挂起请求寄存器,到此之前,中断和事件的信号传输通路都是一致的,也就是说,挂起请求寄存器中记录了外部信号的电平变化. 外部请求信号最后经过编号4的与门,向NVIC中断控制器发出一个中断请求,如果中断屏蔽寄存器的对应位为"0",则该请求信号不能传输到与门的另一端,实现了中断的屏蔽. 明白了外部中断的请求机制,就很容易理解事件的请求机制了.图中红色虚线箭头,标出了外部事件信号的传输路径,外部请求信号经过编号3的或门后,进入编号5的与门,这个与门的作用与编号4的与门类似,用于引入事件屏蔽寄存器的控制;最后脉冲发生器的一个跳变的信号转变为一个单脉冲,输出到芯片中的其它功能模块.从这张图上我们也可以知道,从外部激励信号来看,中断和事件的产生源都可以是一样的.之所以分成2个部分,由于中断是需要CPU参与的,需要软件的中断服务函数才能完成中断后产生的结果;但是事件,是靠脉冲发生器产生一个脉冲,进而由硬件自动完成这个事件产生的结果,当然相应的联动部件需要先设置好,比如引起DMA操作,AD转换等; 简单举例:外部I/O触发AD转换,来测量外部物品的重量;如果使用传统的中断通道,需要I/O触发产生外部中断,外部中断服务程序启动AD转换,AD转换完成中断服务程序提交最后结果;要是使用事件通道,I/O触发产生事件,然后联动触发AD转换,AD转换完成中断服务程序提交最后结果;相比之下,后者不要软件参与AD触发,并且响应速度也更块;要是使用事件触发DMA操作,就完全不用软件参与就可以完成某些联动任务了。 总结: 可以这样简单的认为,事件机制提供了一个完全有硬件自动完成的触发到产生结果的通道,不要软件的参与,降低了CPU的负荷,节省了中断资源,提高了响应速度(硬件总快于软件),是利用硬件来提升CPU芯片处理事件能力的一个有效方法; ———————————————— 版权声明:本文为CSDN博主「flydream0」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/flydream0/java/article/details/8208463
相关资源
广告