利用stm32f103zet6单片机同时生成一个频率为 4-5KHz占空比为50%,峰峰值为 3.3v的方波,频率可以通过按键直接调整及步进可调,步进小于等于1Hz。和频率为12-15KHz峰峰值为2.2v的正弦波,频率可以通过按键直接调整及步进可调,步进小于等于16Hz。生成keil5代码
时间: 2024-02-06 14:12:01 浏览: 61
以下是基于你的要求,给出的一个简单的实现,仅供参考:
```
#include "stm32f10x.h"
#define PI 3.14159265358979323846f
#define SAMPLE_SIZE 256
volatile uint16_t sine_data[SAMPLE_SIZE];
volatile uint32_t freq1 = 5000; // 方波频率,默认为5KHz
volatile uint32_t freq2 = 12000; // 正弦波频率,默认为12KHz
volatile uint8_t step1 = 1; // 方波频率步进值,默认为1Hz
volatile uint8_t step2 = 16; // 正弦波频率步进值,默认为16Hz
volatile uint16_t cnt1 = 0; // 方波计数器
volatile uint16_t cnt2 = 0; // 正弦波计数器
volatile uint16_t sin_index = 0; // 正弦波数据表索引
void TIM1_UP_IRQHandler(void) // 定时器中断处理函数
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
cnt1++;
if (cnt1 > 999) // 方波计数器超过计数范围,重置计数器
{
cnt1 = 0;
}
if (cnt1 < 500) // 占空比为50%
{
GPIO_SetBits(GPIOA, GPIO_Pin_0); // 输出高电平
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 输出低电平
}
cnt2++;
if (cnt2 > freq1) // 正弦波计数器超过设定频率,重置计数器
{
cnt2 = 0;
sin_index += step2; // 修改正弦波数据表索引
if (sin_index >= SAMPLE_SIZE)
{
sin_index -= SAMPLE_SIZE;
}
}
DAC_SetChannel1Data(DAC_Align_12b_R, sine_data[sin_index]); // 输出正弦波数据
}
}
void generate_sine_data(void) // 生成正弦波数据表
{
uint16_t i;
for (i = 0; i < SAMPLE_SIZE; i++)
{
sine_data[i] = (uint16_t)(2048.0f + 2047.0f * sin(2.0f * PI * i / SAMPLE_SIZE));
}
}
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DAC_InitTypeDef DAC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3 | RCC_APB1Periph_DAC, ENABLE);
// 初始化GPIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化定时器1
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 499; // 占空比为50%
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_Cmd(TIM1, ENABLE);
// 初始化定时器2
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
// 初始化DAC
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
// 初始化中断控制器
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);
generate_sine_data(); // 生成正弦波数据表
while (1)
{
// 检测频率调整按键
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == RESET)
{
freq1 += step1; // 修改方波频率
if (freq1 > 5000)
{
freq1 = 4000;
}
}
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_14) == RESET)
{
freq2 += step2; // 修改正弦波频率
if (freq2 > 15000)
{
freq2 = 12000;
}
}
// 延时一段时间
uint32_t delay = 100000;
while (delay--)
;
}
}
```
需要注意的是,以上代码仅为参考,实际应用中需要根据具体情况进行修改和完善。
阅读全文