利用stm32f103zetl单片机同时生成一个频率为 4-5KHz占空比为50%,峰峰值为 3.3v的方波,频率可以通过按键直接调整及步进可调,步进小于等于1Hz。和频率为12-15KHz峰峰值为2.2v的正弦波,频率可以通过按键直接调整及步进可调,步进小于等于16Hz。生成keil5代码
时间: 2024-01-24 11:20:25 浏览: 160
以下是基于Keil5的代码,实现了同时生成一个频率为 4-5KHz占空比为50%,峰峰值为 3.3v的方波和频率为12-15KHz峰峰值为2.2v的正弦波,并且可以通过按键直接调整及步进可调,步进小于等于1Hz和16Hz。
```c
#include "stm32f10x.h"
// 定义时钟频率和周期
#define SYS_CLK_FREQ 72000000
#define CYCLE_FREQ 5000
#define SINE_FREQ_MIN 12000
#define SINE_FREQ_MAX 15000
#define SINE_AMP 2048
#define SINE_OFFSET 2048
// 定义按键引脚
#define KEY_PORT GPIOA
#define KEY_UP_PIN GPIO_Pin_0
#define KEY_DOWN_PIN GPIO_Pin_1
// 定义输出引脚
#define SQUARE_OUT_PORT GPIOB
#define SQUARE_OUT_PIN GPIO_Pin_0
#define SINE_OUT_PORT GPIOB
#define SINE_OUT_PIN GPIO_Pin_1
// 定义计数器和频率变量
volatile uint32_t square_counter = 0;
volatile uint32_t sine_counter = 0;
volatile uint32_t square_freq = CYCLE_FREQ;
volatile uint32_t sine_freq = SINE_FREQ_MIN;
// 初始化函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void TIM_Configuration(void);
void EXTI_Configuration(void);
void NVIC_Configuration(void);
// 主函数
int main(void)
{
// 初始化时钟、GPIO、定时器和中断控制器
RCC_Configuration();
GPIO_Configuration();
TIM_Configuration();
NVIC_Configuration();
// 循环等待
while (1);
}
// RCC配置函数
void RCC_Configuration(void)
{
// 打开GPIO和定时器1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO | RCC_APB2Periph_TIM1, ENABLE);
}
// GPIO配置函数
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 配置按键引脚为输入模式
GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN | KEY_DOWN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY_PORT, &GPIO_InitStructure);
// 配置方波输出引脚为复用模式
GPIO_InitStructure.GPIO_Pin = SQUARE_OUT_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(SQUARE_OUT_PORT, &GPIO_InitStructure);
// 配置正弦波输出引脚为复用模式
GPIO_InitStructure.GPIO_Pin = SINE_OUT_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(SINE_OUT_PORT, &GPIO_InitStructure);
}
// 定时器配置函数
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
// 初始化定时器1
TIM_TimeBaseStructure.TIM_Period = SYS_CLK_FREQ / square_freq - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// 配置定时器1通道1为PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = (SYS_CLK_FREQ / square_freq) / 2 - 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// 配置定时器1为触发源
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
// 初始化定时器3
TIM_TimeBaseStructure.TIM_Period = SYS_CLK_FREQ / SINE_FREQ_MIN - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// 配置定时器3通道2为PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = SINE_AMP + SINE_OFFSET - 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
// 配置定时器3为触发源
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
// 启动定时器1和定时器3
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
// 外部中断配置函数
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
// 配置按键引脚为外部中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
// 配置按键引脚为下降沿触发
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
// 中断控制器配置函数
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 配置定时器1更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 配置定时器3更新中断
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 配置按键中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn | EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 定时器1更新中断服务函数
void TIM1_UP_IRQHandler(void)
{
// 清除定时器1更新中断标志
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
// 计数器加1
square_counter++;
// 如果计数器达到一个周期,则重新设定占空比,计数器清零
if (square_counter >= (SYS_CLK_FREQ / square_freq))
{
TIM_SetCompare1(TIM1, (SYS_CLK_FREQ / square_freq) / 2 - 1);
square_counter = 0;
}
}
// 定时器3更新中断服务函数
void TIM3_IRQHandler(void)
{
// 清除定时器3更新中断标志
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
// 计数器加1
sine_counter++;
// 如果计数器达到一个周期,则重新设定占空比,计数器清零
if (sine_counter >= (SYS_CLK_FREQ / sine_freq))
{
TIM_SetCompare2(TIM3, SINE_AMP * sinf(2 * 3.1415926f * sine_counter / (SYS_CLK_FREQ / sine_freq)) + SINE_OFFSET - 1);
sine_counter = 0;
}
}
// 按键中断服务函数
void EXTI0_IRQHandler(void)
{
// 清除按键0中断标志
EXTI_ClearITPendingBit(EXTI_Line0);
// 频率减小
if (square_freq > CYCLE_FREQ)
{
square_freq -= 1;
TIM_SetAutoreload(TIM1, SYS_CLK_FREQ / square_freq - 1);
}
}
void EXTI1_IRQHandler(void)
{
// 清除按键1中断标志
EXTI_ClearITPendingBit(EXTI_Line1);
// 频率增加
if (square_freq < (CYCLE_FREQ + 1))
{
square_freq += 1;
TIM_SetAutoreload(TIM1, SYS_CLK_FREQ / square_freq - 1);
}
else if (sine_freq < SINE_FREQ_MAX)
{
sine_freq += 16;
TIM_SetAutoreload(TIM3, SYS_CLK_FREQ / sine_freq - 1);
}
else
{
sine_freq = SINE_FREQ_MIN;
TIM_SetAutoreload(TIM3, SYS_CLK_FREQ / sine_freq - 1);
}
}
```
阅读全文