#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
#include "misc.h"
#include "delay.h"
// 引脚定义
#define LED_PIN GPIO_Pin_1
#define LED_PORT GPIOA
#define KEY_PIN GPIO_Pin_1
#define KEY_PORT GPIOB
#define DIG1_PIN GPIO_Pin_12
#define DIG2_PIN GPIO_Pin_13
#define DIG3_PIN GPIO_Pin_14
#define DIG4_PIN GPIO_Pin_15
#define DIG_PORT GPIOB
// 段码引脚对应PB3-PB10
#define SEG_PORT GPIOB
// 状态定义
typedef enum {
SHOW_AEDL,
SHOW_STUDENT_ID,
SHOW_UART_NUM
} DisplayMode;
typedef enum {
LED_BLINK,
LED_OFF
} LedMode;
// 全局变量
LedMode led_mode = LED_BLINK;
DisplayMode disp_mode = SHOW_AEDL;
uint8_t student_id[4] = {0, 0, 0, 1};
uint8_t uart_num[4] = {0, 0, 0, 0};
uint32_t led_tick = 0;
uint8_t led_state = 0;
uint32_t key_press_time = 0;
uint8_t key_pressed = 0;
uint8_t uart_receive_count = 0;
// 共阳数码管段码表 (0-9, A, b, C, d, E, F, L)
const uint8_t seg_table[14] = {
0xC0, // 0: 共阳,低电平点亮
0xF9, // 1
0xA4, // 2
0xB0, // 3
0x99, // 4
0x92, // 5
0x82, // 6
0xF8, // 7
0x80, // 8
0x90, // 9
0x88, // A
0x86, // E
0xA1,
0xC7 // L
};
// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void TIM2_Configuration(void);
void NVIC_Configuration(void);
void display_digit(uint8_t digit, uint8_t position);
void display_update(void);
void send_uart_data(uint8_t *data, uint16_t len);
void delay_ms(uint32_t ms);
int main(void) {
// 初始化
RCC_Configuration();
GPIO_Configuration();
USART_Configuration();
TIM2_Configuration();
NVIC_Configuration();
// 初始LED状态
GPIO_SetBits(LED_PORT, LED_PIN);
while (1) {
// LED控制
if (led_mode == LED_BLINK) {
if (led_tick >= 1500) { // 1.5秒切换一次状态
led_tick = 0;
led_state = !led_state;
if (led_state) {
GPIO_ResetBits(LED_PORT, LED_PIN); // 点亮
} else {
GPIO_SetBits(LED_PORT, LED_PIN); // 熄灭
}
}
}
// 按键处理
if (GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == 0) { // 按键按下
if (!key_pressed) {
key_pressed = 1;
key_press_time = 0;
} else {
key_press_time++; // 每1ms增加1
}
} else { // 按键释放
if (key_pressed) {
key_pressed = 0;
if (key_press_time < 500) { // 短按 (<500ms)
// 切换LED状态
led_mode = (led_mode == LED_BLINK) ? LED_OFF : LED_BLINK;
if (led_mode == LED_OFF) {
GPIO_SetBits(LED_PORT, LED_PIN); // 强制熄灭
} else {
led_tick = 0;
led_state = 0;
}
// 发送短按信息
uint8_t short_msg[] = "Short\n";
send_uart_data(short_msg, sizeof(short_msg)-1);
} else { // 长按 (>=500ms)
// 切换显示模式,但如果是串口数字模式则只切回AEDL
if (disp_mode == SHOW_UART_NUM) {
disp_mode = SHOW_AEDL;
} else {
disp_mode = (disp_mode == SHOW_AEDL) ? SHOW_STUDENT_ID : SHOW_AEDL;
}
// 发送长按信息
uint8_t long_msg[] = "Long\n";
send_uart_data(long_msg, sizeof(long_msg)-1);
}
}
}
// 更新显示
display_update();
// 短延时,降低CPU占用
delay_ms(1);
}
}
// 系统时钟配置
void RCC_Configuration(void) {
RCC_HSEConfig(RCC_HSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // 8MHz * 9 = 72MHz
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
RCC_HCLKConfig(RCC_SYSCLK_Div1); // HCLK = 72MHz
RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = 72MHz
RCC_PCLK1Config(RCC_HCLK_Div2); // PCLK1 = 36MHz
// 使能外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 禁用JTAG,仅启用SWD调试(释放PB3、PB4、PA15)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
}
// GPIO配置
void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// LED配置 (推挽输出)
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED_PORT, &GPIO_InitStructure);
// 按键配置 (上拉输入)
GPIO_InitStructure.GPIO_Pin = KEY_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY_PORT, &GPIO_InitStructure);
// 数码管位选配置 (推挽输出)
GPIO_InitStructure.GPIO_Pin = DIG1_PIN | DIG2_PIN | DIG3_PIN | DIG4_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(DIG_PORT, &GPIO_InitStructure);
// 数码管段选配置 (推挽输出)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 |
GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(SEG_PORT, &GPIO_InitStructure);
// USART1配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// USART配置
void USART_Configuration(void) {
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// USART1配置: 115200 8N1
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
// 使能USART1接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// 配置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 使能USART1
USART_Cmd(USART1, ENABLE);
}
// 定时器2配置,用于延时函数
void TIM2_Configuration(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 7199; // 1ms中断 (72MHz / 10000 = 7200Hz)
TIM_TimeBaseStructure.TIM_Prescaler = 9;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
// NVIC配置 NVIC_Configuration
void NVIC_Configuration(void) {
NVIC_InitTypeDef NVIC_Configuration;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 定时器2中断
NVIC_Configuration.NVIC_IRQChannel = TIM2_IRQn;
NVIC_Configuration.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_Configuration.NVIC_IRQChannelSubPriority = 0;
NVIC_Configuration.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Configuration);
}
// 显示单个数字到指定位置
void display_digit(uint8_t digit, uint8_t position) {
// 关闭所有位选
GPIO_SetBits(DIG_PORT, DIG1_PIN | DIG2_PIN | DIG3_PIN | DIG4_PIN);
// 设置段码
GPIO_Write(SEG_PORT, (GPIO_ReadOutputData(SEG_PORT) & 0xFFFFF00F) |
((uint32_t)seg_table[digit] << 3));
// 打开对应位选
switch (position) {
case 0: GPIO_ResetBits(DIG_PORT, DIG1_PIN); break;
case 1: GPIO_ResetBits(DIG_PORT, DIG2_PIN); break;
case 2: GPIO_ResetBits(DIG_PORT, DIG3_PIN); break;
case 3: GPIO_ResetBits(DIG_PORT, DIG4_PIN); break;
}
// 短暂延时,确保显示稳定
delay_ms(1);
}
// 更新显示
void display_update(void) {
static uint8_t pos = 0;
switch (disp_mode) {
case SHOW_AEDL:
// 显示"AEDL"
switch (pos) {
case 0: display_digit(11, 0); break; // A
case 1: display_digit(12, 1); break; // E
case 2: display_digit(13, 2); break; // d
case 3: display_digit(14, 3); break; // L
}
break;
case SHOW_STUDENT_ID:
// 显示学号后四位
display_digit(student_id[pos], pos);
break;
case SHOW_UART_NUM:
// 显示串口接收的数字
display_digit(uart_num[pos], pos);
break;
}
// 循环显示四个位置
pos = (pos + 1) % 4;
}
// 发送数据到串口
void send_uart_data(uint8_t *data, uint16_t len) {
for (uint16_t i = 0; i < len; i++) {
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, data[i]);
}
}
// 定时器2中断服务函数
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// 更新LED计时
if (led_mode == LED_BLINK) {
led_tick++;
}
}
}
// USART1中断服务函数
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
uint8_t data = USART_ReceiveData(USART1);
// 只处理数字字符
if (data >= '0' && data <= '9') {
uart_num[uart_receive_count++] = data - '0';
// 收到4位数字后,切换到显示串口数字模式
if (uart_receive_count >= 4) {
uart_receive_count = 0;
disp_mode = SHOW_UART_NUM;
}
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
// 毫秒级延时函数
void delay_ms(uint32_t ms) {
for (uint32_t i = 0; i < ms; i++) {
for (uint32_t j = 0; j < 7200; j++);
}
}
这是我写的,但是现在'显示AEDL时却显示的8888,显示0001时显示的0000