以下buck稳压代码中的占空比是谁控制的,是怎么改变的,是要人为写代码,还是TTM1-CCR1内部自己控制的,请分析出其流程,简明易懂#include "tim.h"
extern uint16_t TIM1_Impluse;
float z = 0;
const uint32_t spwm[400] = {
4200,4265,4331,4397,4463,4529,4595,4660,4726,4791,4857,4922,4987,5051,5116,5180,
5244,5308,5371,5434,5497,5560,5622,5684,5746,5807,5868,5928,5988,6047,6106,6165,
6223,6280,6337,6394,6450,6505,6560,6615,6668,6721,6774,6826,6877,6927,6977,7026,
7075,7122,7169,7216,7261,7306,7350,7393,7436,7477,7518,7558,7597,7636,7673,7710,
7746,7781,7815,7848,7880,7911,7942,7971,8000,8027,8054,8080,8105,8128,8151,8173,
8194,8214,8233,8251,8268,8283,8298,8312,8325,8337,8348,8358,8366,8374,8381,8387,
8391,8395,8397,8399,8400,8399,8397,8395,8391,8387,8381,8374,8366,8358,8348,8337,
8325,8312,8298,8283,8268,8251,8233,8214,8194,8173,8151,8128,8105,8080,8054,8027,
8000,7971,7942,7911,7880,7848,7815,7781,7746,7710,7673,7636,7597,7558,7518,7477,
7436,7393,7350,7306,7261,7216,7169,7122,7075,7026,6977,6927,6877,6826,6774,6721,
6668,6615,6560,6505,6450,6394,6337,6280,6223,6165,6106,6047,5988,5928,5868,5807,
5746,5684,5622,5560,5497,5434,5371,5308,5244,5180,5116,5051,4987,4922,4857,4791,
4726,4660,4595,4529,4463,4397,4331,4265,4200,4134,4068,4002,3936,3870,3804,3739,
3673,3608,3542,3477,3412,3348,3283,3219,3155,3091,3028,2965,2902,2839,2777,2715,
2653,2592,2531,2471,2411,2352,2293,2234,2176,2119,2062,2005,1949,1894,1839,1784,
1731,1678,1625,1573,1522,1472,1422,1373,1324,1277,1230,1183,1138,1093,1049,1006,
963,922,881,841,802,763,726,689,653,618,584,551,519,488,457,428,
399,372,345,319,294,271,248,226,205,185,166,148,131,116,101,87,
74,62,51,41,33,25,18,12,8,4,2,0,0,0,2,4,
8,12,18,25,33,41,51,62,74,87,101,116,131,148,166,185,
205,226,248,271,294,319,345,372,399,428,457,488,519,551,584,618,
653,689,726,763,802,841,881,922,963,1006,1049,1093,1138,1183,1230,1277,
1324,1373,1422,1472,1522,1573,1625,1678,1731,1784,1839,1894,1949,2005,2062,2119,
2176,2234,2293,2352,2411,2471,2531,2592,2653,2715,2777,2839,2902,2965,3028,3091,
3155,3219,3283,3348,3412,3477,3542,3608,3673,3739,3804,3870,3936,4002,4068,4134
};
//TIM1的GPIO
static void TIM_GPIO_Config(void)
{
GPIO_InitTypeDef TIM_GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB, ENABLE);//开钟
/*-----------------------------PA8,PA7------------------------------------*/
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1);//引脚复用 主 PA8,PA7
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM1);//引脚复用 补
TIM_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //模拟模式GPIO_Mode_AN/F
TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8; //引脚
TIM_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; //高速
TIM_GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
TIM_GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &TIM_GPIO_InitStruct); //写入
TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &TIM_GPIO_InitStruct);
/*-----------------------------------------------------------------------*/
/*-----------------------------PA9,PB14------------------------------------*/
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_TIM1);//引脚复用 主
GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_TIM1);//引脚复用 补
TIM_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //模拟模式GPIO_Mode_AN/F
TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //引脚
TIM_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; //高速
TIM_GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
TIM_GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &TIM_GPIO_InitStruct); //写入
TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
GPIO_Init(GPIOB, &TIM_GPIO_InitStruct);
/*-----------------------------------------------------------------------*/
/*-----------------------------PA10,PB1------------------------------------*/
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_TIM1);//引脚复用 主
GPIO_PinAFConfig(GPIOB,GPIO_PinSource1,GPIO_AF_TIM1);//引脚复用 补
TIM_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //模拟模式GPIO_Mode_AN/F
TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; //引脚
TIM_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; //高速
TIM_GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
TIM_GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOA, &TIM_GPIO_InitStruct); //写入
TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOB, &TIM_GPIO_InitStruct);
/*-----------------------------------------------------------------------*/
}
//TIM1
static void TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);///使能时钟
//168MHZ->20kHZ 主频/(计数+1)*(预分频系数+1)
//168MHz/8 * 1050 = 20khz
/*-----------------------------基本结构体------------------------------------*/
TIM_TimeBaseInitStructure.TIM_Period = (4200-1); //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=(2-1); //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //1分频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; //不需要重复计数
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure); //初始化TIM
/*-----------------------------基本结构体------------------------------------*/
// 配置TIM1更新事件作为TRGO输出
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
/*-----------------------------输出比较------------------------------------*/
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //pwm模式选择
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; ///使能输出通道
TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable; //使能互补通道
TIM_OCInitStruct.TIM_Pulse = TIM1_Impluse; //预设占空比
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //PWM1和2中的CH和CCR之间值的大小(多用pwm1的模式1)
TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;
//当使用了刹车功能时,两路PWM1和2都会被强制禁止,进而输出我们配置的的空闲先状态
TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set; //刹车时输出通道的状态 Set = high
TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset; //刹车时互补通道的状态 Reset = low
TIM_OC1Init(TIM1, &TIM_OCInitStruct); //使能通道1
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); /* 使能通道1重载 */
TIM_OCInitStruct.TIM_Pulse = TIM1_Impluse;
TIM_OC2Init(TIM1, &TIM_OCInitStruct);
TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);
TIM_OCInitStruct.TIM_Pulse = TIM1_Impluse;
TIM_OC3Init(TIM1, &TIM_OCInitStruct);
TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);
/*-----------------------------输出比较------------------------------------*/
/*-----------------------------死区刹车------------------------------------*/
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; //开启死区
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; //开启1空闲状态
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; //不同的锁定级别 (看BDTR寄存器)
TIM_BDTRInitStructure.TIM_DeadTime = 84; //刹车时间,(看BDTR寄存器中的DTG[7:0])
//11转换成二进制为0000 1011 死区时间看[7;5]位,此处为000
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; //允许刹车
//BKIN 测到低电平 比较信号禁止
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; //高极性
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable; //自动输出使能(刹车输入无效)
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); //写入
/*-----------------------------死区刹车------------------------------------*/
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //允许定时器更新中断 | TIM_IT_Trigger
TIM_Cmd(TIM1,ENABLE); //使能定时器
TIM_CtrlPWMOutputs(TIM1, ENABLE); //主动输出使能
}
static void TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/*-----------------------------中断------------------------------------*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //分组
NVIC_InitStructure.NVIC_IRQChannel=TIM1_UP_TIM10_IRQn; //定时器1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断
NVIC_Init(&NVIC_InitStructure); //写入
/*-----------------------------中断------------------------------------*/
}
void TIM_Init(void)
{
TIM_NVIC_Config();
TIM_GPIO_Config();
TIM_Mode_Config();
}
#include "stm32f4xx.h"
#include "delay.h"
#include "oled.h"
#include "stdio.h"
#include "stdlib.h"
#include "arm_math.h"
#include "pid.h"
#include "./adc/bsp_adc.h"
#include "tim.h"
#include "General_Tim.h"
extern float voltage1, voltage2, voltage3;
extern float Vout_actual;
extern volatile uint8_t adc_data_ready;
float Target= 1; // 目标输出电压
float pid_out;
volatile uint32_t systick_count = 0;
static uint32_t last_display_time = 0;
int main(void)
{
GENERAL_TIM_Init();
OLED_Init();
delay_ms(500);
Adc_Init();
TIM_Init();
char str[40];
while(1)
{
if(adc_data_ready)
{
adc_data_ready = 0;
ADC_Read(); // 读取并计算电压
// PID计算
pid_out = pid_control(0.8f, 0.05f, 0.02f, Target, Vout_actual);
if(Vout_actual > Target * 1.2f) // 过压保护
TIM1->CCR1 = 0;// 触发保护逻辑
// 安全更新PWM (限制在0-8400)
uint16_t pwm_val = (uint16_t)(pid_out * 84); // 0-100% -> 0-8400
if(pwm_val > 8400) pwm_val = 8400;
TIM1->CCR1 = pwm_val;
}
if (systick_count- last_display_time >= 10)
{
last_display_time = systick_count;
sprintf(str, "Vout: %.2fV", Vout_actual);
OLED_ShowString(0, 1, (u8*)str, 12);
OLED_Refresh_Gram();
}
}
}
#include "stm32f4xx_it.h"
#include "oled.h"
#include <math.h>
#include "./adc/bsp_adc.h"
#include "pid.h"
extern float Vout_actual;
extern float Target ; // 目标输出电压
extern float pid_out;
extern volatile uint32_t systick_count;
volatile uint8_t adc_data_ready = 0;// 全局变量
uint16_t TIM1_Impluse;//高级定时器占空比
// 简化中断处理函数
void TIM1_UP_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update))
{
TIM_ClearFlag(TIM1,TIM_IT_Update);
}
}
void DMA2_Stream0_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
{
adc_data_ready = 1; // 设置数据就绪标志
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
}
}
// 使用TIM2作为毫秒计时器
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
systick_count++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
void NMI_Handler(void)
{
}
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{}
}
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{}
}
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{}
}
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{}
}
void DebugMon_Handler(void)
{
}
void SVC_Handler(void)
{
}
void PendSV_Handler(void)
{
}
void SysTick_Handler(void)
{
}
#include "./adc/bsp_adc.h"
#include "oled.h"
#include "stdio.h"
#include "stdlib.h"
char st[40];
__IO uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL]={0};
float voltage1=0, voltage2=0, voltage3=0;
float Vout_actual;
static void ADC_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*=====================通道1======================*/
// 使能 GPIO 时钟
RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK1,ENABLE);
// 配置 IO
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//不上拉不下拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(ADC_GPIO_PORT1, &GPIO_InitStructure);
/*=====================通道2======================*/
// 使能 GPIO 时钟
RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK2,ENABLE);
// 配置 IO
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//不上拉不下拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(ADC_GPIO_PORT2, &GPIO_InitStructure);
/*=====================通道3=======================*/
// 使能 GPIO 时钟
RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK3,ENABLE);
// 配置 IO
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//不上拉不下拉
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(ADC_GPIO_PORT3, &GPIO_InitStructure);
}
static void ADC_Mode_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
// ------------------DMA Init 结构体参数 初始化--------------------------
// ADC1使用DMA2,数据流0,通道0,这个是手册固定死的
// 开启DMA时钟
RCC_AHB1PeriphClockCmd(ADC_DMA_CLK, ENABLE);
// 外设基址为:ADC 数据寄存器地址
DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_DR_ADDR;
// 存储器地址,实际上就是一个内部SRAM的变量
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC_ConvertedValue;
// 数据传输方向为外设到存储器
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
// 缓冲区大小为,指一次传输的数据量
DMA_InitStructure.DMA_BufferSize = RHEOSTAT_NOFCHANEL;
// 外设寄存器只有一个,地址不用递增
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
// 存储器地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
// // 外设数据大小为半字,即两个字节
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
// 存储器数据大小也为半字,跟外设数据大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
// 循环传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
// 禁止DMA FIFO ,使用直连模式
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
// FIFO 大小,FIFO模式禁止时,这个不用配置
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
// 选择 DMA 通道,通道存在于流中
DMA_InitStructure.DMA_Channel = ADC_DMA_CHANNEL;
//初始化DMA流,流相当于一个大的管道,管道里面有很多通道
DMA_Init(ADC_DMA_STREAM, &DMA_InitStructure);
// 使能DMA传输完成中断
DMA_ITConfig(ADC_DMA_STREAM, DMA_IT_TC, ENABLE);
// 使能DMA流
DMA_Cmd(ADC_DMA_STREAM, ENABLE);
// 开启ADC时钟
RCC_APB2PeriphClockCmd(ADC_CLK , ENABLE);
// -------------------ADC Common 结构体 参数 初始化------------------------
// 独立ADC模式
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
// 时钟为fpclk x分频
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
// 禁止DMA直接访问模式
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
// 采样时间间隔
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
// -------------------ADC Init 结构体 参数 初始化--------------------------
ADC_StructInit(&ADC_InitStructure);
// ADC 分辨率
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
// 扫描模式,多通道采集需要
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
// 连续转换
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
//禁止外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
//外部触发通道,
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; // TIM1触发;
//数据右对齐
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
//转换通道 1个
ADC_InitStructure.ADC_NbrOfConversion = RHEOSTAT_NOFCHANEL;
ADC_Init(ADC_, &ADC_InitStructure);
//---------------------------------------------------------------------------
// 配置 ADC 通道转换顺序和采样时间周期
ADC_RegularChannelConfig(ADC_, ADC_CHANNEL1, 1,
ADC_SampleTime_480Cycles);
ADC_RegularChannelConfig(ADC_, ADC_CHANNEL2, 2,
ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig(ADC_, ADC_CHANNEL3, 3,
ADC_SampleTime_15Cycles);
// 使能DMA请求 after last transfer (Single-ADC mode)
ADC_DMARequestAfterLastTransferCmd(ADC_, ENABLE);
// 使能ADC DMA
ADC_DMACmd(ADC_, ENABLE);
// 使能ADC
ADC_Cmd(ADC_, ENABLE);
// //开始adc转换,软件触发
// ADC_SoftwareStartConv(ADC_);
}
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//配置DMA
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 修改ADC读取函数 (adc部分)
#define VOLTAGE_SCALE 4.0f // 根据实际分压电阻调整 (12V→3V分压)
void ADC_Read(void)
{
// 正确计算电压值 (考虑分压比例)
voltage1 = ADC_ConvertedValue[0] * 3.3f* 0.000244140625;
Vout_actual= voltage1;
}
void Adc_Init(void)
{
ADC_GPIO_Config();
ADC_Mode_Config();
ADC_NVIC_Config();
}
#include "pid.h"
//float kp, ki, kd; // PID参数
//float last_error = 0,last_error_2 = 0 , last_output, setpoint, input, output;
float pid_control(float KP, float KI, float KD, float Set_Point, float Now_Point) {
static float integral = 0;
static float prev_error = 0;
const float max_integral = 100.0f / KI; // 积分限幅
float error = Set_Point - Now_Point;
// 积分项(带抗饱和)
integral += error;
if(integral > max_integral) integral = max_integral;
else if(integral < -max_integral) integral = -max_integral;
// 微分项
float derivative = error - prev_error;
// PID输出
float output = KP * error + KI * integral + KD * derivative;
// 输出限幅
if(output > 100.0f) output = 100.0f;
else if(output < 0.0f) output = 0.0f;
prev_error = error;
return output;
}
#include "General_Tim.h"
// 中断优先级配置
static void GENERAL_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler 都有
// * TIM_CounterMode TIMx,x[6,7]没有,其他都有
// * TIM_Period 都有
// * TIM_ClockDivision TIMx,x[6,7]没有,其他都有
// * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef;
// *-----------------------------------------------------------------------------
// */
static void GENERAL_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 1ms中断 (TIM2在APB1上,时钟84MHz)
TIM_TimeBaseStructure.TIM_Period = 8400 - 1; // 84MHz/8400 = 10kHz
TIM_TimeBaseStructure.TIM_Prescaler = 8400 - 1; // 84MHz/8400 = 10kHz → 0.1ms
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);
}
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_NVIC_Config();
GENERAL_TIM_Mode_Config();
}
/*********************************************END OF FILE**********************/
#ifndef __BSP_ADC_H
#define __BSP_ADC_H
#include "stm32f4xx.h"
#define RHEOSTAT_NOFCHANEL 3
/*=====================通道1 IO======================*/
// ADC IO宏定义
#define ADC_GPIO_PORT1 GPIOE
#define ADC_GPIO_PIN1 GPIO_Pin_5
#define ADC_GPIO_CLK1 RCC_AHB1Periph_GPIOE
#define ADC_CHANNEL1 ADC_Channel_15
/*=====================通道2 IO ======================*/
// ADC IO宏定义
#define ADC_GPIO_PORT2 GPIOA
#define ADC_GPIO_PIN2 GPIO_Pin_2
#define ADC_GPIO_CLK2 RCC_AHB1Periph_GPIOA
#define ADC_CHANNEL2 ADC_Channel_2
/*=====================通道3 IO ======================*/
// ADC IO宏定义
#define ADC_GPIO_PORT3 GPIOA
#define ADC_GPIO_PIN3 GPIO_Pin_3
#define ADC_GPIO_CLK3 RCC_AHB1Periph_GPIOA
#define ADC_CHANNEL3 ADC_Channel_3
// ADC 序号宏定义
#define ADC_ ADC1
#define ADC_CLK RCC_APB2Periph_ADC1
// ADC DR寄存器宏定义,ADC转换后的数字值则存放在这里
#define RHEOSTAT_ADC_DR_ADDR ((u32)ADC1+0x4c)
// ADC DMA 通道宏定义,这里我们使用DMA传输
#define ADC_DMA_CLK RCC_AHB1Periph_DMA2
#define ADC_DMA_CHANNEL DMA_Channel_0
#define ADC_DMA_STREAM DMA2_Stream0
void Adc_Init(void);
void ADC_Read(void);
#endif /* __BSP_ADC_H */