为什么改成下午这样,oled屏都不亮了#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];
uint32_t time = 0; // ms 计时变量
extern volatile uint8_t adc_data_ready;
extern volatile uint8_t tim_update_flag;
extern volatile uint32_t last_adc_value;
float six = 0;
// 全局状态变量
enum {STATE_INIT, STATE_RUNNING, STATE_FAULT} system_state = STATE_INIT;
int main(void) {
// 初始化外设
Adc_Init();
TIM_Init();
OLED_Init();
TIM2_Init();
// 启动转换
ADC_SoftwareStartConv(ADC1);
while(1)
{
// 状态机管理
switch(system_state)
{
case STATE_INIT:
if ( time == 1000 ) /* 1000 * 1 ms = 1s 时间到 */
{
time = 0;
TIM_CtrlPWMOutputs(TIM1, ENABLE);
system_state = STATE_RUNNING;
} break;
case STATE_RUNNING:
// 过压保护
if(Vout_actual > 15.0f)
{
char st[40];
TIM_CtrlPWMOutputs(TIM1, DISABLE);
system_state = STATE_FAULT;
OLED_ShowString(WORD_WIDTH*0,WORD_HIGH*4,(u8 *)st,WORD_SIZE);
} break;
case STATE_FAULT:
// 需要手动复位
break;
}
}
}
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 = %d",TIM1->CCR2);
OLED_ShowString(WORD_WIDTH*0,WORD_HIGH*3,(u8 *)str,WORD_SIZE);
OLED_Refresh_Gram();
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
#include "stm32f4xx_it.h"
#include "oled.h"
#include <math.h>
#include "./adc/bsp_adc.h"
#include "pid.h"
#include "bsp_GeneralTim.h"
#include "bsp_GeneralTim.h"
float Taget=12;
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;
// PID计算(使用新的PID控制器)
static PIDController pid;
// 在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);
}
}
void TIM1_UP_TIM10_IRQHandler(void) {
if (TIM_GetITStatus(TIM1, TIM_IT_Update)) {
if (adc_data_ready) {
uint32_t sum = 0;
for (int i=0; i<ADC_BUFFER_SIZE; i++) {
sum += ADC_ConvertedValue[i];
}
Vout_actual = (sum * 3.3f) / (ADC_BUFFER_SIZE * 4096.0f);
adc_data_ready = 0;
static uint8_t pid_initialized = 0;
if (!pid_initialized) {
PID_Init(&pid, 2.6f, 1.5f, 0.1f, 100.0f, 0.0f);
pid_initialized = 1;
}
pid_out = PID_Compute(&pid, 12.0f, Vout_actual);
// 计算占空比:pid_out是百分比,所以乘以(ARR+1)再除以100
TIM1_Impluse = (uint16_t)(pid_out * (TIM1->ARR + 1) / 100.0f);
// 限幅保护(实际上PID输出已经限幅,这里可以省略,但为了安全)
if (TIM1_Impluse > TIM1->ARR)
TIM1_Impluse = TIM1->ARR;
// 更新PWM(注意:我们只更新通道1,即PA8,其他通道可以不用更新)
TIM1->CCR1 = TIM1_Impluse;
// 同时更新其他通道(如果硬件上需要同步更新)
// TIM1->CCR2 = TIM1_Impluse;
// TIM1->CCR3 = TIM1_Impluse;
}
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
void GENERAL_TIM_IRQHandler (void)
{
if ( TIM_GetITStatus( GENERAL_TIM, TIM_IT_Update) != RESET )
{
time++;
TIM_ClearITPendingBit(GENERAL_TIM , TIM_FLAG_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"
#define ADC_BUFFER_SIZE 32
__IO uint16_t ADC_ConvertedValue[ADC_BUFFER_SIZE] = {0}; // 修正数组大小
volatile uint8_t current_buffer = 0;
volatile uint8_t adc_buffer_ready = 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 = ADC_BUFFER_SIZE; // 缓冲区大小
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();
}
#ifndef __BSP_ADC_H
#define __BSP_ADC_H
#include "stm32f4xx.h"
#define ADC_BUFFER_SIZE 32 // 增加缓冲区大小
extern __IO uint16_t ADC_ConvertedValue[ADC_BUFFER_SIZE]; // 在bsp_adc.c中定义
#define ADC_CHANNELS 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_GetVoltage(void);
//float ADC_ReadVoltage(void);
#endif /* __BSP_ADC_H */
#include "pid.h"
void PID_Init(PIDController* pid, float kp, float ki, float kd, float max, float min) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->integral = 0;
pid->prev_error = 0;
pid->max_output = max;
pid->min_output = min;
}
float PID_Compute(PIDController* 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);
}
#include "bsp_GeneralTim.h"
// 中断优先级配置
static void GENERAL_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
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;
// 开启定时器时钟,即内部时钟CK_INT=72M
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;
// 时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;
// 时钟分频因子 ,没用到不用管
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
// 清除计数器中断标志位
TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update);
// 开启计数器中断
TIM_ITConfig(GENERAL_TIM,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_NVIC_Config();
GENERAL_TIM_Mode_Config();
}
/*********************************************END OF FILE**********************/
#ifndef __BSP_GENERALTIME_H
#define __BSP_GENERALTIME_H
#include "stm32f4xx.h"
/**************通用定时器TIM参数定义,只限TIM2、3、4、5************/
// 当需要哪个定时器的时候,只需要把下面的宏定义改成1即可
#define GENERAL_TIM2 0
#define GENERAL_TIM3 1
#define GENERAL_TIM4 0
#define GENERAL_TIM5 0
#if GENERAL_TIM2
#define GENERAL_TIM TIM2
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM2
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM2_IRQn
#define GENERAL_TIM_IRQHandler TIM2_IRQHandler
#elif GENERAL_TIM3
#define GENERAL_TIM TIM3
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM3
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM3_IRQn
#define GENERAL_TIM_IRQHandler TIM3_IRQHandler
#elif GENERAL_TIM4
#define GENERAL_TIM TIM4
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM4
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM4_IRQn
#define GENERAL_TIM_IRQHandler TIM4_IRQHandler
#elif GENERAL_TIM5
#define GENERAL_TIM TIM5
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM5
#define GENERAL_TIM_Period (1000-1)
#define GENERAL_TIM_Prescaler 71
#define GENERAL_TIM_IRQ TIM5_IRQn
#define GENERAL_TIM_IRQHandler TIM5_IRQHandler
#endif
/**************************函数声明********************************/
void GENERAL_TIM_Init(void);
void TIM2_Init(void);
#endif /* __BSP_GENERALTIME_H */
最新发布