数码管亮度控制器的设计

怎么通过分频改变占空比来控制数码管的亮暗程度 想要些思路 还有一些程序上的建议 因为对于程序编写知识有点差 在quartus9.0中编程

数码管亮度控制器的设计可以通过以下步骤实现:

  1. 选择一个定时器模块,例如STM32的TIM模块,来生成一个固定频率的PWM信号。

  2. 将PWM信号连接到数码管的控制引脚上,通过改变PWM信号的占空比来控制数码管的亮度。

  3. 通过改变PWM信号的频率来改变亮度的调节范围。频率越高,亮度调节范围越小;频率越低,亮度调节范围越大。

  4. 根据所选定时器模块的不同,可能需要配置多个寄存器来实现PWM信号的生成和控制。

以下是一个简单的程序示例:




#include "stm32f4xx.h"

TIM_HandleTypeDef htim2;

void SystemClock_Config(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();

  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_TIM2_CLK_ENABLE();

  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&htim2);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500; // PWM占空比
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

  while (1)
  {
    // 在此处添加亮度调节代码
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}

这段代码
使用了STM32的TIM2模块来生成PWM信号,并将信号连接到GPIOA的第5个引脚上。

在时序逻辑电路中,除了实现时钟的奇偶分频,还会涉及到时钟的占空比问题,现就该问题进行如下分析。

实现占空比为50%的分频电路很简单,对于偶分频电路只需将cnt计数到一半时进行输出q的翻转即可。比如8分频的输出q,只需在cnt == 3(8÷2 - 1)的时候进行翻转,因为cnt计数是从0计数到7,即0,1,2,3,4,5,6,7,其中3正好是中间点。
若要实现占空比可调,q1和q2要根据不同的cnt值进行翻转。比如8分频电路,q1在cnt==0翻转(此输出相当于16分频),q2在cnt==6的时候进行翻转(此输出也相当于16分频),只不过q2相对于q1往后延迟了6个cycle,令q=q1 ^ q2(异或),最终可得到占空比为6/8=75%

详细可以查看csnd的连接:https://blog.csdn.net/qq_15062763/article/details/100373223

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/156325
  • 这篇博客你也可以参考下:关于函数调用返回引用错误并且每次调用不一致的分析与解决
  • 除此之外, 这篇博客: 从时间复杂度和空间复杂度来看斐波那契数列中的 首先我们来看一下什么叫斐波那契数列: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 斐波那契数列是指这样一个数列:

    1 1 2 3 5 8 13 21 34 55 ~ ~ ~等这样的一组数列。
    它的规律是第三个数等于前两个数之和

    #include<stdio.h>
    #include<stdlib.h>
    int Fibonacci_1(size_t n)//注意返回值可能会很大,但c语言中最大整数为4294967295
    {                        //测试后只能计算前46个斐波那契额数列
    	int  first,second,third;//非递归算法
    	int i;
    	first=0;
    	second=1;
    	if(n<=2)
    	{
    		return 1;
    	}
    	for(i=2; i<=n; i++)
    	{
    		third=first+second;
    		first=second;
    		second=third;
    	}
    	return third;
    }
    int Fibonacci_2(size_t n)//递归算法
    {
    	if(n<=2)
    	{
    		return 1;
    	}
    	else
    		return Fibonacci_1(n-1)+Fibonacci_1(n-2);
    }
    int main()
    {
    	size_t n=40;
    	printf("非递归算法第%d个斐波那契数为>:%d\n",n,Fibonacci_1(n));
    	printf("递归算法第%d个斐波那契数为>:%d\n",n,Fibonacci_2(n));
    	system("pause");
    	return 0;
    }
    

    运行结果如下:

    在这里插入图片描述

    两个代码看起来相差不了多少,但从时间复杂度和空间复杂度上比较,还是相差很远的。

    时间复杂度

    递归算法:
    在这里插入图片描述

    非递归: 通过观察循环次数就可以发现,非递归只需要循环 n次就可以计算出第n个斐波那契数,所以它的时间复杂度时O(n);

    这时当假如n为100时,递归算法需要计算2^100次,二非递归只需要计算100次,这时候递归算法可能需要很长一段时间,而非递归却很快,这就通过时间复杂度体现了两者算法的差别。

    空间复杂度
    在这里插入图片描述

    而非递归方法开辟了三个变量空间,空间复杂度为O(1),而递归的是O(n);但现在随着硬件的发展,空间复杂度已经不那么重要了。
    所以总体来说非递归的算法效率更高。

  • 您还可以看一下 吴刚老师的【吴刚大讲堂】电商导航视觉识别设计课程中的 按导航标签数量分类方法总结及其对移动视觉优化的影响小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    针对数码管亮度控制器的问题,可以使用定时器和占空比控制方法进行设计。具体步骤如下:

    1. 首先选择一个适合的定时器,并配置为PWM输出模式。PWM输出信号的标准方波频率应该大于数码管刷新的最小频率,一般应该在几千Hz到几万Hz之间。

    2. 接着,设置PWM输出信号的初始占空比。一般来说,数码管亮度最大时占空比为100%,亮度最小时为0%。可以根据自己的需求来设置占空比,或者提供一个可调节的旋钮或按钮以供用户自行调节。

    3. 当需要改变数码管的亮度时,可以通过改变PWM输出信号的占空比来达到目的。通过改变占空比的方式可以达到调节亮度的目的,当占空比较大时,数码管显得更亮,而占空比较小时,数码管亮度更低。可以通过定时器中断的方式,每隔一段时间改变占空比,来实现数码管亮度的缓慢变化,以达到更加柔和的效果。

    下面是一个利用STM32CubeMX和Keil MDK编写的代码示例:

    #include "main.h"
    #include "stm32f1xx_hal.h"
    
    /* 定义定时器句柄和PWM输出句柄 */
    TIM_HandleTypeDef htim1;
    TIM_OC_InitTypeDef sConfigOC;
    
    /* 定义全局变量记录当前占空比和变化方向 */
    uint32_t dutyCycle = 0;
    uint32_t dutyCycleDir = 1;
    
    /* 定义函数原型 */
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_TIM1_Init(void);
    
    int main(void)
    {
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_TIM1_Init();
    
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    
      while (1)
      {
        /* 每隔一定时间改变PWM输出占空比 */
        HAL_Delay(10);
    
        dutyCycle += dutyCycleDir;
    
        /* 如果占空比已经达到最大或最小值,则改变变化方向 */
        if (dutyCycle >= 100)
        {
          dutyCycle = 100;
          dutyCycleDir = -1;
        }
        else if (dutyCycle <= 0)
        {
          dutyCycle = 0;
          dutyCycleDir = 1;
        }
    
        /* 更新PWM输出占空比 */
        sConfigOC.Pulse = (TIM1->ARR + 1) * dutyCycle / 100;
        HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
        HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
      }
    }
    
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct;
      RCC_ClkInitTypeDef RCC_ClkInitStruct;
    
      __HAL_RCC_PWR_CLK_ENABLE();
      __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    static void MX_TIM1_Init(void)
    {
      TIM_MasterConfigTypeDef sMasterConfig;
    
      htim1.Instance = TIM1;
      htim1.Init.Prescaler = 0;
      htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
      htim1.Init.Period = 7199;
      htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
      if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
      {
        Error_Handler();
      }
    
      sConfigOC.OCMode = TIM_OCMODE_PWM1;
      sConfigOC.Pulse = 0;
      sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
      sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
      sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
      sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    
      if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
      {
        Error_Handler();
      }
    
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
      if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
    
    }
    
    static void MX_GPIO_Init(void)
    {
      GPIO_InitTypeDef GPIO_InitStruct;
    
      __HAL_RCC_GPIOC_CLK_ENABLE();
      /**TIM1 GPIO Configuration    
      PC0     ------> TIM1_CH1 
      */
      GPIO_InitStruct.Pin = GPIO_PIN_0;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    }
    
    void Error_Handler(void)
    {
      __disable_irq();
      while (1)
      {
      }
    }
    

    代码中使用了TIM1作为PWM输出,初始化了一个10ms的定时器,并且每隔10ms改变PWM输出占空比。为了方便理解,没有采用中断的方式,而是使用了HAL_Delay函数。

    在程序运行过程中,每隔10ms,就会改变PWM输出占空比,并重新启动PWM输出。这样,数码管的亮度就会随着时间的推移而变化。

    注意,因为不同型号的STM32芯片的寄存器分布和功能可能有所不同,所以具体的寄存器配置可能会不同。代码示例中的配置是针对STM32F103C8T6芯片的,具体又ST公司提供的STM32CubeMX软件自动生成。

    当然,也可以使用其他的MCU和其他的开发环境来设计数码管亮度控制器,大体的设计思路应该是相同的。

c语言控制led数码管,数码管&LED
可以借鉴下
https://blog.csdn.net/weixin_36378347/article/details/117241230

提个建议,具体的你去实施:
1,用74HC165去控制数码管的点亮
2,在程序中用时钟做一个PWM,用一个脚作为输出,接到74HC165的CE脚,可以用来控制数码管的亮度
实际产品中实现过