怎么通过分频改变占空比来控制数码管的亮暗程度 想要些思路 还有一些程序上的建议 因为对于程序编写知识有点差 在quartus9.0中编程
数码管亮度控制器的设计可以通过以下步骤实现:
选择一个定时器模块,例如STM32的TIM模块,来生成一个固定频率的PWM信号。
将PWM信号连接到数码管的控制引脚上,通过改变PWM信号的占空比来控制数码管的亮度。
通过改变PWM信号的频率来改变亮度的调节范围。频率越高,亮度调节范围越小;频率越低,亮度调节范围越大。
根据所选定时器模块的不同,可能需要配置多个寄存器来实现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
斐波那契数列是指这样一个数列:
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);但现在随着硬件的发展,空间复杂度已经不那么重要了。
所以总体来说非递归的算法效率更高。
针对数码管亮度控制器的问题,可以使用定时器和占空比控制方法进行设计。具体步骤如下:
首先选择一个适合的定时器,并配置为PWM输出模式。PWM输出信号的标准方波频率应该大于数码管刷新的最小频率,一般应该在几千Hz到几万Hz之间。
接着,设置PWM输出信号的初始占空比。一般来说,数码管亮度最大时占空比为100%,亮度最小时为0%。可以根据自己的需求来设置占空比,或者提供一个可调节的旋钮或按钮以供用户自行调节。
当需要改变数码管的亮度时,可以通过改变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脚,可以用来控制数码管的亮度
实际产品中实现过