为什么oled屏上显示TIM1->CCR2的值为0,在tim中断中不是已经将pid_out的值赋给TIM1->CCR2了吗(oled屏上显示的Duty=49.580,即pid_out的值),而且为什么PA9引脚上PWM波的正占空比为0.34%左右,而PA8引脚上PWM波的正占空比为49%左右,还有这测量的电压#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 "bsp_GeneralTim.h"
float pid_out = 0;
float Vout_actual = 0;
extern __IO uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL];
extern volatile uint8_t adc_data_ready ;
extern volatile uint8_t tim_update_flag;
extern volatile uint32_t last_adc_value ;
float six = 0;
int main(void)
{
Adc_Init();
TIM_Init();
OLED_Init();
TIM2_Init();
while(1)
{}
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET )
{
char str[40];
sprintf(str,"Vout = %.3f",Vout_actual);
OLED_ShowString(WORD_WIDTH*0,WORD_HIGH*0,(u8 *)str,WORD_SIZE);
sprintf(str,"Duty = %.3f",pid_out);
OLED_ShowString(WORD_WIDTH*0,WORD_HIGH*1,(u8 *)str,WORD_SIZE);
sprintf(str,"test = %.3f",six);
OLED_ShowString(WORD_WIDTH*0,WORD_HIGH*2,(u8 *)str,WORD_SIZE);
OLED_Refresh_Gram();
sprintf(str,"TIM1->CCR2 = %.3f",TIM1->CCR2);
OLED_ShowString(WORD_WIDTH*0,WORD_HIGH*3,(u8 *)str,WORD_SIZE);
OLED_Refresh_Gram();
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
//// 输入20V→输出15V:kp=0.3-0.6, ki=0.05-0.2, kd=0.01-0.05
////输入35V→输出20V:kp=0.2-0.4, ki=0.02-0.1, kd=0.005-0.02
//
//
//
// pid.kp = 0.5f; // 从较小值开始调试
// pid.ki = 0.1f;
// pid.kd = 0.01f;
// pid.max_output = 100.0f;
// pid.min_output = 0.0f;
// pid.integral = 0;
// pid.prev_error = 0;
#include "stm32f4xx_it.h"
#include "oled.h"
#include <math.h>
#include "./adc/bsp_adc.h"
#include "pid.h"
#include "bsp_GeneralTim.h"
float Taget=12;
extern uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL];
extern float voltage1;
extern float pid_out;
extern float Vout_actual;
extern uint16_t TIM1_Impluse ;//高级定时器占空比
volatile uint8_t adc_data_ready = 0;
volatile uint8_t tim_update_flag=0 ;
volatile uint32_t last_adc_value = 0;
extern volatile uint32_t time;
extern float six;
// 在DMA中断中仅设置标志
void DMA2_Stream0_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
{
adc_data_ready = 1; // 仅设置标志
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
}
}
// 在PWM中断中处理数据
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update) == SET)
{
if(adc_data_ready) {
// 1. 读取并转换最新ADC值
Vout_actual = ADC_ConvertedValue[0] * 3.3f * 0.000244140625;
// 2. 重置标志
adc_data_ready = 0;
// 3. PID计算
pid_out =pid_control(2.7,1.5,0.1,12,Vout_actual);
// 4. 更新PWM
TIM1->CCR2 = pid_out; // 使用通道2
six = 1;
}
TIM_ClearITPendingBit(TIM1, 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 "tim.h"
uint16_t TIM1_Impluse = 4200;//预设占空比
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);
/*-----------------------------------------------------------------------*/
// TIM_GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; //模拟模式 pa6死刹
// TIM_GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; //引脚
// TIM_GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; //高速
// TIM_GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
// TIM_GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; //浮空
// GPIO_Init(GPIOA, &TIM_GPIO_InitStruct); //写入
}
//TIM1
static void TIM_A1_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 = (8400-1); //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=(1-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
/*-----------------------------基本结构体------------------------------------*/
/*-----------------------------输出比较------------------------------------*/
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 = 20; //刹车时间,(看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_A1_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_A1_NVIC_Config();
TIM_GPIO_Config();
TIM_A1_Mode_Config();
}
#include "./adc/bsp_adc.h"
#include "bsp_GeneralTim.h"
#include "stm32f4xx_adc.h"
__IO uint16_t ADC_ConvertedValue[1]={0};
volatile uint8_t current_buffer = 0;
extern volatile uint32_t time;
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);
}
void ADC_DMA_Config(void) {
DMA_InitTypeDef DMA_InitStructure;
// 1. 使能 DMA 时钟
RCC_AHB1PeriphClockCmd(ADC_DMA_CLK, ENABLE);
// 2. 配置 DMA 参数
DMA_InitStructure.DMA_Channel = ADC_DMA_CHANNEL; // DMA 通道 0
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADC_ConvertedValue; // 目标地址:内存缓冲区
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // 修正外设地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // 外设到内存
DMA_InitStructure.DMA_BufferSize = 1; // 缓冲区大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; // 单通道禁用地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设数据大小:半字(16位)
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 内存数据大小:半字(16位)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // 禁用 FIFO 模式
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; // FIFO 阈值
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // 内存突发传输:单次
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 外设突发传输:单次
// 3. 初始化 DMA
DMA_Init(ADC_DMA_STREAM, &DMA_InitStructure);
// 4. 使能 DMA 中断(传输完成、传输错误)
DMA_ITConfig(ADC_DMA_STREAM, DMA_IT_TC | DMA_IT_TE | DMA_IT_HT, ENABLE);
// 5. 使能 DMA 流
DMA_Cmd(ADC_DMA_STREAM, ENABLE);
}
void ADC_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
// 1. 使能 ADC 时钟
RCC_APB2PeriphClockCmd(ADC_CLK, ENABLE);
// 2. 配置 ADC 通用参数
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; // ADC 时钟分频:PCLK2/4
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1 ; // DMA 访问模式
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; // 采样延迟
ADC_CommonInit(&ADC_CommonInitStructure);
// 3. 配置 ADC 参数
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; // 12位分辨率
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 扫描模式使能
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; // 软件触发
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; // 任意值
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1 ; // 转换通道数
ADC_Init(ADC_, &ADC_InitStructure);
// 4. 配置 ADC 通道(通道4,PA4)
ADC_RegularChannelConfig(ADC_, ADC_Channel_4, 1, ADC_SampleTime_84Cycles);
// 5. 使能 ADC DMA
ADC_DMACmd(ADC_, ENABLE);
// 6. 使能 ADC
ADC_Cmd(ADC_, ENABLE);
// 7. 启动 ADC 转换
ADC_SoftwareStartConv(ADC_);
}
static void ADC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
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);
}
void Adc_Init(void)
{
ADC_GPIO_Config();
ADC_DMA_Config();
ADC_Config();
ADC_NVIC_Config();
}
//float ADC_ReadVoltage(void)
// {
//
// static uint8_t initialized = 0;
// if(!initialized)
// {
// Adc_Init();
// initialized = 1;
// }
//
//
// // 直接读取全局数组
// return ADC_ConvertedValue[0] * 3.3f /4096;
//}
#ifndef __BSP_ADC_H
#define __BSP_ADC_H
#include "stm32f4xx.h"
#define RHEOSTAT_NOFCHANEL 1
/*=====================通道1 IO======================*/
// ADC IO宏定义
#define ADC_GPIO_PORT1 GPIOA
#define ADC_GPIO_PIN1 GPIO_Pin_4
#define ADC_GPIO_CLK1 RCC_AHB1Periph_GPIOA
#define ADC_CHANNEL1 ADC_Channel_4
// ADC 序号宏定义
#define ADC_ ADC1
#define ADC_CLK RCC_APB2Periph_ADC1
// ADC DR寄存器宏定义,ADC转换后的数字值则存放在这里
#define RHEOSTAT_ADC_DR_ADDR ((u32)ADC1+0x4c)
// ADC DMA 通道宏定义,这里我们使用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);
//float ADC_ReadVoltage(void);
#endif /* __BSP_ADC_H */
#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)
{
kp = KP;
ki = KI;
kd = KD;
setpoint = Set_Point;
input = Now_Point;
float error = setpoint - input;
float delta_error = error - last_error;
output += kp*delta_error + ki*error + kd*(error-2*last_error+last_error_2);
last_error_2 = last_error;
last_error = error;
last_output = output;
//输出限幅
if(output >= 100.0f ) output = 100.0f;
return output;
}
//float pid_control(PID_Controller* pid, float setpoint, float input) {
// // 计算当前误差
// float error = setpoint - input;
//
// // 比例项
// float p_term = pid->kp * error;
//
// // 积分项(带抗饱和)
// pid->integral += error;
//
// // 积分限幅
// if(pid->integral > pid->max_output)
// pid->integral = pid->max_output;
// else if(pid->integral < pid->min_output)
// pid->integral = pid->min_output;
//
// float i_term = pid->ki * pid->integral;
//
// // 微分项(标准实现)
// float d_term = pid->kd * (error - pid->prev_error);
//
// // PID输出
// float output = p_term + i_term + d_term;
//
// // 输出限幅
// if(output > pid->max_output) output = pid->max_output;
// else if(output < pid->min_output) output = pid->min_output;
//
// // 更新误差历史
// pid->prev_error = error;
//
// return output;
//}
#include "bsp_GeneralTim.h"
void TIM2_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseInitStructure.TIM_Period = (168000-1);
TIM_TimeBaseInitStructure.TIM_Prescaler= (1000-1);
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_ARRPreloadConfig(TIM2,ENABLE);
TIM_Cmd(TIM2,ENABLE);
}
最新发布