利用stm32f103zet6单片机同时生成一个频率为 4-5KHz占空比为50%,峰峰值为 3.3v的方波,频率可以通过按键直接调整及步进可调,步进小于等于1Hz。和频率为12-15KHz峰峰值为2.2v的正弦波,频率可以通过按键直接调整及步进可调,步进小于等于16Hz。生成keil5代码
时间: 2024-02-09 18:07:23 浏览: 66
首先,需要了解STM32F103ZET6单片机的定时器和PWM模块的使用方法。
下面是实现方波和正弦波的代码:
```c
#include "stm32f10x.h"
#include <math.h>
#define PI 3.14159265358979323846
volatile uint16_t pwm_value = 0;
volatile uint16_t sin_value = 0;
volatile uint16_t freq = 5000;
volatile uint16_t sin_freq = 12000;
volatile uint16_t sin_amp = 1023;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
pwm_value++;
if (pwm_value >= 100)
{
pwm_value = 0;
}
if (pwm_value < 50)
{
GPIO_SetBits(GPIOA, GPIO_Pin_0);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
}
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
sin_value = (sin_value + 1) % 360;
uint16_t sin_output = (uint16_t)(sin(sin_value * PI / 180.0) * sin_amp + sin_amp);
TIM_SetCompare1(TIM3, sin_output);
}
}
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line0);
freq += 1;
if (freq > 5000)
{
freq = 5000;
}
}
}
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line1) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line1);
freq -= 1;
if (freq < 4000)
{
freq = 4000;
}
}
}
void EXTI2_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line2) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line2);
sin_freq += 16;
if (sin_freq > 15000)
{
sin_freq = 15000;
}
}
}
void EXTI3_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line3) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line3);
sin_freq -= 16;
if (sin_freq < 12000)
{
sin_freq = 12000;
}
}
}
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 199;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
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);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 100;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_TimeBaseStructure.TIM_Period = 71;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_Init(&NVIC_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_Init(&NVIC_InitStructure);
while (1);
}
```
在上面的代码中,我们使用了TIM2定时器和PWM模块来生成方波,使用TIM3定时器和PWM模块来生成正弦波。同时,我们还使用了外部中断来控制频率的调整。
在TIM2的中断服务函数中,我们根据pwm_value的值来判断方波的占空比。在TIM3的中断服务函数中,我们使用sin_value来生成正弦波的PWM输出。
当按下外部中断0和1的按钮时,我们分别增加和减少方波的频率。当按下外部中断2和3的按钮时,我们分别增加和减少正弦波的频率。
需要注意的是,由于STM32F103ZET6单片机的TIM2和TIM3定时器频率相同,我们需要使用不同的分频器来生成不同频率的输出。
另外,为了方便起见,我们在代码中直接使用了math库中的sin函数来生成正弦波,实际上,也可以通过查表的方式来生成正弦波。
阅读全文