STM32流水灯并用按键控制速度用数码管显示速度
时间: 2023-10-22 22:09:48 浏览: 162
以下是一种可能的STM32流水灯并用按键控制速度用数码管显示速度的实现方法:
首先,需要连接STM32开发板上的LED灯和一个4位共阳数码管。LED灯可以连接到任意GPIO引脚,这里假设连接到PA0~PA7这8个引脚上。数码管可以使用74HC595芯片进行驱动,具体连接方式可以参考其数据手册。这里假设使用PB0、PB1、PB2、PB3分别连接到74HC595的SER、SRCLK、RCLK、OE引脚。
接下来,需要编写代码实现流水灯和按键控制速度。以下是一个简单的示例代码:
```c
#include "stm32f10x.h"
#include "delay.h"
#include "shift_reg.h"
#include "key.h"
#define LED_NUM 8
#define SPEED_MAX 10
#define SPEED_MIN 1
uint8_t leds[LED_NUM] = {1, 2, 4, 8, 16, 32, 64, 128};
uint8_t speed = 5;
void init_leds(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3
| GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void shift_reg_write(uint8_t data) {
for (int i = 0; i < 8; i++) {
if (data & 0x80) {
GPIO_SetBits(GPIOB, GPIO_Pin_0);
} else {
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
}
GPIO_SetBits(GPIOB, GPIO_Pin_1);
GPIO_ResetBits(GPIOB, GPIO_Pin_1);
data <<= 1;
}
GPIO_SetBits(GPIOB, GPIO_Pin_2);
GPIO_ResetBits(GPIOB, GPIO_Pin_2);
}
void display_speed(uint8_t speed) {
static uint8_t digits[4] = {0};
digits[3] = speed / 100;
digits[2] = (speed % 100) / 10;
digits[1] = speed % 10;
shift_reg_write(0xff);
shift_reg_write(leds[digits[0]]);
shift_reg_write(leds[digits[1]]);
shift_reg_write(leds[digits[2]]);
shift_reg_write(leds[digits[3]]);
}
void init_timer(void) {
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 200 - speed * 20;
TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void) {
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
static uint8_t index = 0;
static uint8_t direction = 0;
if (direction == 0) {
GPIO_SetBits(GPIOA, GPIO_Pin_0 + index);
index++;
if (index >= LED_NUM) {
index = LED_NUM - 2;
direction = 1;
}
} else {
GPIO_ResetBits(GPIOA, GPIO_Pin_7 - index);
index--;
if (index >= LED_NUM) {
index = 1;
direction = 0;
}
}
TIM_SetAutoreload(TIM3, 200 - speed * 20);
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
int main(void) {
delay_init();
init_leds();
shift_reg_init();
key_init();
init_timer();
while (1) {
uint8_t key = key_scan();
if (key == KEY_UP) {
if (speed < SPEED_MAX) {
speed++;
display_speed(speed);
}
} else if (key == KEY_DOWN) {
if (speed > SPEED_MIN) {
speed--;
display_speed(speed);
}
}
}
}
```
代码主要分为以下几个部分:
1. 初始化LED灯和数码管的GPIO引脚。
2. 实现74HC595芯片的串行写入函数。
3. 实现数码管显示数字的函数。
4. 初始化定时器,用于控制流水灯的速度。
5. 实现定时器中断服务函数,用于控制流水灯的移动方向和速度。
6. 在主函数中不断检测按键,根据按键调整流水灯的速度并显示在数码管上。
需要注意的是,这里使用了一些外部库,包括延时函数(delay.h)、74HC595芯片驱动函数(shift_reg.h)和按键扫描函数(key.h)。这些库的实现可以在网上找到,这里不再赘述。同时,需要将定时器的时钟源配置为72MHz,否则计算速度和定时器时间会出现错误。
总的来说,这个示例代码实现了一个简单的流水灯,并用按键控制速度,同时在数码管上显示当前速度。可以作为初学者学习STM32的一个小项目。