给出实验3的基础实验和扩展实验代码,只能用文档中的库函数编写
时间: 2024-12-23 10:21:16 浏览: 6
### 实验三:GD32F303ZKT6 微控制器的定时器实验
#### 基础实验:LED1 发光二极管的闪烁
**实验目的**:
1. 使用定时器 1 (TIMER1) 实现 LED1 发光二极管的闪烁,闪烁频率为 0.5 秒。
**实验代码**:
```c
#include "gd32f30x.h"
// 初始化定时器 1
void timer1_init(void)
{
// 使能 TIM1 时钟
rcu_periph_clock_enable(RCU_TIM1);
// 配置定时器参数
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = (SystemCoreClock / 1000000 - 1); // 1us 分频
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 500000; // 500ms
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIM1, &timer_initpara);
// 使能定时器 1 更新中断
timer_interrupt_enable(TIM1, TIMER_INT_UP);
// 使能定时器 1
timer_enable(TIM1);
}
// 定时器 1 中断服务函数
void TIMER1_IRQHandler(void)
{
if (RESET != timer_interrupt_flag_get(TIM1, TIMER_INT_FLAG_UP))
{
// 清除定时器 1 更新中断标志
timer_interrupt_flag_clear(TIM1, TIMER_INT_FLAG_UP);
// 切换 LED1 的状态
gpio_bit_toggle(GPIOB, GPIO_PIN_0);
}
}
// 主函数
int main(void)
{
// 使能 GPIOB 时钟
rcu_periph_clock_enable(RCU_GPIOB);
// 配置 PB0 为推挽输出
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
// 初始化定时器 1
timer1_init();
// 使能定时器 1 中断
nvic_irq_enable(TIMER1_IRQn, 0, 0);
while (1)
{
// 主循环
}
}
```
#### 扩展实验
##### 1. 将基础实验实现的内容改为中断方式实现
**实验代码**:
已在基础实验中实现。
##### 2. 利用定时器 2 (TIMER2) 的中断方式实现对 8 位共阴动态显示数码管的动态描述显示,扫描时间间隔为 1 ms,将自己的完整学号以左流水的方式显示在数码管上,流水的速度为 0.5 秒。
**实验代码**:
```c
#include "gd32f30x.h"
#define SEGMENT_COUNT 8
#define DIGIT_COUNT 4
// 学号数组
uint8_t student_id[] = {0x31, 0x32, 0x33, 0x34}; // 示例学号,实际使用时替换为自己的学号
// 数码管段码表
const uint8_t segment_code[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
// 初始化定时器 2
void timer2_init(void)
{
// 使能 TIM2 时钟
rcu_periph_clock_enable(RCU_TIM2);
// 配置定时器参数
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = (SystemCoreClock / 1000000 - 1); // 1us 分频
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 1000; // 1ms
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIM2, &timer_initpara);
// 使能定时器 2 更新中断
timer_interrupt_enable(TIM2, TIMER_INT_UP);
// 使能定时器 2
timer_enable(TIM2);
}
// 初始化 GPIO
void gpio_init_digital_display(void)
{
// 使能 GPIOF 时钟
rcu_periph_clock_enable(RCU_GPIOF);
// 配置 PF0-PF7 为推挽输出
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
// 配置 PF8-PF15 为推挽输出
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 |
GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
}
// 显示数码管
void display_digit(uint8_t digit, uint8_t value)
{
// 设置段码
gpio_port_write(GPIOF, (segment_code[value] << 0) | (1 << (digit + 8)));
}
// 定时器 2 中断服务函数
void TIMER2_IRQHandler(void)
{
static uint8_t current_digit = 0;
static uint8_t current_index = 0;
if (RESET != timer_interrupt_flag_get(TIM2, TIMER_INT_FLAG_UP))
{
// 清除定时器 2 更新中断标志
timer_interrupt_flag_clear(TIM2, TIMER_INT_FLAG_UP);
// 显示当前数码管
display_digit(current_digit, student_id[current_index]);
// 更新当前数码管索引
current_digit = (current_digit + 1) % DIGIT_COUNT;
// 更新当前学号索引
if (++current_index >= sizeof(student_id)) {
current_index = 0;
}
// 每 500 次中断切换一次学号
if ((current_digit == 0) && (current_index == 0)) {
current_index = (current_index + 1) % sizeof(student_id);
}
}
}
// 主函数
int main(void)
{
// 初始化 GPIO
gpio_init_digital_display();
// 初始化定时器 2
timer2_init();
// 使能定时器 2 中断
nvic_irq_enable(TIMER2_IRQn, 0, 0);
while (1)
{
// 主循环
}
}
```
##### 3. 利用定时器 3 (TIMER3) 的中断方式实现对行阳列阴的 8x8 点阵 LED 的驱动,并在 8x8 点阵 LED 上循环显示数字 0-9。
**实验代码**:
```c
#include "gd32f30x.h"
#define ROW_COUNT 8
#define COL_COUNT 8
// 数字 0-9 对应的点阵图案
const uint8_t digit_patterns[10][8] = {
{0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF}, // 0
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // 1
{0xFF, 0x81, 0x81, 0x02, 0x02, 0x02, 0x02, 0xFF}, // 2
{0xFF, 0x81, 0x81, 0x02, 0x02, 0x81, 0x81, 0xFF}, // 3
{0x81, 0x81, 0x81, 0xFF, 0x02, 0x02, 0x02, 0x02}, // 4
{0xFF, 0x02, 0x02, 0x02, 0x02, 0x81, 0x81, 0xFF}, // 5
{0xFF, 0x02, 0x02, 0x02, 0x02, 0x81, 0x81, 0xFF}, // 6
{0xFF, 0x81, 0x81, 0x02, 0x02, 0x02, 0x02, 0x02}, // 7
{0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF}, // 8
{0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x02} // 9
};
// 初始化定时器 3
void timer3_init(void)
{
// 使能 TIM3 时钟
rcu_periph_clock_enable(RCU_TIM3);
// 配置定时器参数
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = (SystemCoreClock / 1000000 - 1); // 1us 分频
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 1000; // 1ms
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIM3, &timer_initpara);
// 使能定时器 3 更新中断
timer_interrupt_enable(TIM3, TIMER_INT_UP);
// 使能定时器 3
timer_enable(TIM3);
}
// 初始化 GPIO
void gpio_init_matrix_led(void)
{
// 使能 GPIOB 和 GPIOC 时钟
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
// 配置 PB0-PB7 为推挽输出
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
// 配置 PC0-PC7 为推挽输出
gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
}
// 显示点阵 LED
void display_matrix_led(uint8_t row, uint8_t col_pattern)
{
// 设置行
gpio_port_write(GPIOB, ~(1 << row));
// 设置列
gpio_port_write(GPIOC, col_pattern);
}
// 定时器 3 中断服务函数
void TIMER3_IRQHandler(void)
{
static uint8_t current_row = 0;
static uint8_t current_digit = 0;
if (RESET != timer_interrupt_flag_get(TIM3, TIMER_INT_FLAG_UP))
{
// 清除定时器 3 更新中断标志
timer_interrupt_flag_clear(TIM3, TIMER_INT_FLAG_UP);
// 显示当前行
display_matrix_led(current_row, digit_patterns[current_digit][current_row]);
// 更新当前行索引
current_row = (current_row + 1) % ROW_COUNT;
// 更新当前数字索引
if (current_row == 0) {
current_digit = (current_digit + 1) % 10;
}
}
}
// 主函数
int main(void)
{
// 初始化 GPIO
gpio_init_matrix_led();
// 初始化定时器 3
timer3_init();
// 使能定时器 3 中断
nvic_irq_enable(TIMER3_IRQn, 0, 0);
while (1)
{
// 主循环
}
}
```
##### 4. 利用定时器 2 (TIMER2) 的 CH2 (PB0) 引脚产生呼吸灯显示效果。
**实验代码**:
```c
#include "gd32f30x.h"
// 初始化定时器 2
void timer2_pwm_init(void)
{
// 使能 TIM2 时钟
rcu_periph_clock_enable(RCU_TIM2);
// 配置定时器参数
timer_parameter_struct timer_initpara;
timer_initpara.prescaler = (SystemCoreClock / 1000000 - 1); // 1us 分频
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 10000; // 10ms
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIM2, &timer_initpara);
// 配置 PWM 输出
timer_channel_parameter_struct channel_initpara;
channel_initpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
channel_initpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
channel_initpara.octriaload = TIMER_OC_TRIALOAD_ENABLE;
channel_initpara.ocfast = TIMER_OC_FAST_DISABLE;
channel_initpara.ocprescaler = TIMER_OC_PRESCALER_1;
channel_initpara.ocnumpulse = 0;
channel_initpara.outputstate = TIMER_CCX_ENABLE;
channel_initpara.outputnstate = TIMER_CCXN_DISABLE;
channel_initpara.forceoutput = TIMER_OC_FORCE_OUTPUT_CLEAR;
channel_initpara.channelpinpol = TIMER_CHANNL_INPOLARITY_RISING;
channel_initpara.channelcomctl = TIMER_CHANNEL_COMCTL_NONE;
channel_initpara.channelcommask = 0x00;
// 配置 CH2 为 PWM 输出
timer_channel_output_config(TIM2, TIMER_CH_2, &channel_initpara);
timer_channel_output_mode_config(TIM2, TIMER_CH_2, TIMER_OC_MODE_PWM1);
timer_channel_output_pulse_value_config(TIM2, TIMER_CH_2, 0);
timer_channel_output_shadow_config(TIM2, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);
// 使能定时器 2
timer_enable(TIM2);
}
// 主函数
int main(void)
{
// 使能 GPIOB 时钟
rcu_periph_clock_enable(RCU_GPIOB);
// 配置 PB0 为复用推挽输出
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
// 初始化定时器 2 PWM
timer2_pwm_init();
// 呼吸灯效果
uint16_t duty_cycle = 0;
uint16_t direction = 1;
while (1)
{
// 更新占空比
duty_cycle += direction * 10;
if (duty_cycle > 1000) {
duty_cycle = 1000;
direction = -1;
} else if (duty_cycle < 0) {
duty_cycle = 0;
direction = 1;
}
// 设置 PWM 占空比
timer_channel_output_pulse_value_config(TIM2, TIMER_CH_2, duty_cycle);
// 延迟
for (volatile uint32_t i = 0; i < 100000; i++);
}
}
```
以上代码展示了如何使用 GD32F303ZKT6 微控制器的定时器功能实现各种实验任务。每个实验都使用了文档中提供的库函数进行初始化和操作。
阅读全文