为什么一把tim中断给注销掉,该程序的oled屏就可以亮了,我想知道ADC,TIM,DMA在下面这个buck电路中起着什么样的作用,而且为什么这个程序达不到稳压的作用,还有oled屏上的实际电压是F4板子上那个引脚的,它应该显示多少伏#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”
extern float voltage1, voltage2, voltage3;
extern float Vout_actual;
float Target= 12; // 目标输出电压12
float a;
//extern __IO uint16_t ADC_ConvertedValue;
extern uint16_t TIM_Advance_Impulse;
volatile uint32_t sys_tick = 0; // 全局计时器变量
extern float pid_out;
extern uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL];
#define FILTER_SAMPLES 5
float voltage_buffer[FILTER_SAMPLES] = {0};
uint8_t buffer_index = 0;
// 修改ADC读取函数
void ADC_Read(void) {
// 原始读取
voltage1 = (float)ADC_ConvertedValue[0] * 0.000244140625 * 3.3;
// 移动平均滤波 voltage_buffer[buffer_index] = voltage1; buffer_index = (buffer_index + 1) % FILTER_SAMPLES; float sum = 0; for (int i = 0; i < FILTER_SAMPLES; i++) { sum += voltage_buffer[i]; } Vout_actual = sum / FILTER_SAMPLES;
}
int main(void)
{
#define MAX_VOLTAGE 13.0f // 最大允许电压
// 在主循环中添加 if (Vout_actual > MAX_VOLTAGE) { // 触发保护:关闭PWM输出 TIM_CtrlPWMOutputs(TIM1, DISABLE); OLED_ShowString(0, 3, (u8*)"OVER VOLTAGE!", 16); while(1); // 死循环保护 } // 1. 初始化SysTick if(SysTick_Config(SystemCoreClock / 1000)) { // 错误处理 while(1); } // 3. 初始化外设 OLED_Init(); delay_ms(500); // 确保OLED完全启动 Adc_Init(); TIM_Init(); // TIM1中断已禁用 uint32_t last_pid_time = 0; const uint32_t pid_interval = 10; // PID计算间隔(ms) char str[40]; // 添加滤波初始化 for (int i = 0; i < FILTER_SAMPLES; i++) { voltage_buffer[i] = 0; } while(1) { ADC_Read(); // 读取并滤波ADC值 // 每10ms执行一次PID计算 if (sys_tick - last_pid_time >= pid_interval) { last_pid_time = sys_tick; pid_out = pid_control(2.0, 0.1, 0.01, Target, Vout_actual); TIM1->CCR1 = (uint16_t)(pid_out * 8.4); // 8400/100=84 → 8.4 // 显示PID输出 sprintf(str, "PID Out: %.1f%%", pid_out); OLED_ShowString(0, 2, (u8*)str, 12); } // 显示实际电压 sprintf(str, "Vout: %.2fV", Vout_actual); OLED_ShowString(0, 1, (u8*)str, 12); OLED_Refresh_Gram(); delay_ms(1); }
}
#include “stm32f4xx_it.h”
#include “oled.h”
#include <math.h>
#include “./adc/bsp_adc.h”
#include “pid.h”
extern uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL];
extern float voltage1;
uint16_t TIM_Advance_Impulse ;//高级定时器占空比
extern float Vout_actual;
float Vout_set; // 目标输出电压
float pid_out;
extern volatile uint32_t sys_tick;
extern float pid_out;
volatile uint32_t tim1_update_count = 0;
#define PID_CALC_INTERVAL 20 // 每20次中断(即1ms,如果中断频率20kHz)计算一次
void TIM1_UP_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update) == SET)
{
tim1_update_count++;
if (tim1_update_count >= PID_CALC_INTERVAL)
{
tim1_update_count = 0;
// // 读取全局变量Vout_actual,由主循环更新
// pid_out = pid_control (5 , 0.25, 0 ,Vout_set ,Vout_actual);
// TIM1->CCR1 = pid_out;
}
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
void DMA2_Stream0_IRQHandler(void) { if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET) { DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); }
}
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)
{
sys_tick++; // 每毫秒增加1
}
#include “delay.h”
#include “core_cm4.h”
#include “misc.h”
// couter 减1的时间 等于 1/systick_clk
// 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
// 同时 CTRL 的 countflag 位会置1
// 这一个循环的时间为 reload * (1/systick_clk)
void delay_us( __IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000000);
for(i=0;i<us;i++) { // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1 while( !((SysTick->CTRL)&(1<<16)) ); } // 关闭SysTick定时器 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
void delay_ms( __IO uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000);
for(i=0;i<ms;i++) { // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1 // 当置1时,读取该位会清0 while( !((SysTick->CTRL)&(1<<16)) ); } // 关闭SysTick定时器 SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}
/***********************END OF FILE/
#include “oled.h”
#include “oledfont.h”
#include “delay.h”
//OLED的显存
//存放格式如下.
//[0]0 1 2 3 … 127
//[1]0 1 2 3 … 127
//[2]0 1 2 3 … 127
//[3]0 1 2 3 … 127
//[4]0 1 2 3 … 127
//[5]0 1 2 3 … 127
//[6]0 1 2 3 … 127
//[7]0 1 2 3 … 127
u8 OLED_GRAM[128][8];
#if OLED_MODE==0
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{
u8 i;
OLED_DC=cmd;
OLED_CS=0;
for(i=0;i<8;i++)
{
OLED_SCL=0;
if(dat&0x80)
OLED_SDA=1;
else
OLED_SDA=0;
OLED_SCL=1;
dat<<=1;
}
OLED_CS=1;
OLED_DC=1;
}
#endif
#if OLED_MODE==1
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{
OLED_DATA_OUT(dat);
OLED_RST=cmd;
OLED_CS=0;
OLED_WR=0;
OLED_WR=1;
OLED_CS=1;
OLED_DC=1;
}
#endif
#if OLED_MODE==2
void OLED_WR_Byte(u8 dat,u8 cmd)
{
}
#endif
//更新显存到LCD
void OLED_Refresh_Gram(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD);
}
//开启OLED显示
void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
{
OLED_GRAM[n][i]=0;
}
}
OLED_Refresh_Gram();//更新显示
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
u8 pos,bx,temp=0;
if(x>127||y>63)return;//超出范围了.
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
if(t)OLED_GRAM[x][pos]|=temp;
else OLED_GRAM[x][pos]&=~temp;
}
void OLED_DrawLine(u8 x1, u8 y1, u8 x2, u8 y2)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //计算坐标增量 delta_y=y2-y1; uRow=x1; uCol=y1; if(delta_x>0)incx=1; //设置单步方向 else if(delta_x==0)incx=0;//垂直线 else {incx=-1;delta_x=-delta_x;} if(delta_y>0)incy=1; else if(delta_y==0)incy=0;//水平线 else{incy=-1;delta_y=-delta_y;} if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 else distance=delta_y; for(t=0;t<=distance+1;t++ )//画线输出 { OLED_DrawPoint(uRow,uCol,1);//画点 xerr+=delta_x ; yerr+=delta_y ; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } }
}
void OLED_DrawRectangle(u8 x1, u8 y1, u8 x2, u8 y2)
{
OLED_DrawLine(x1,y1,x2,y1);
OLED_DrawLine(x1,y1,x1,y2);
OLED_DrawLine(x1,y2,x2,y2);
OLED_DrawLine(x2,y1,x2,y2);
}
//x1,y1,x2,y2 填充区域的对角坐标
//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
//dot:0,清空;1,填充
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)
{
u8 x,y;
for(x=x1;x<=x2;x++)
{
for(y=y1;y<=y2;y++)
{
OLED_DrawPoint(x,y,dot);
}
}
OLED_Refresh_Gram();//更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 12/16/24
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{
u8 temp,t,t1;
u8 y0=y;
u8 csize=(size/8+((size%8)?1:0)) * (size/2); //得到字体一个字符对应点阵集所占的字节数
chr=chr-’ ';//得到偏移后的值
for(t=0;t<csize;t++)
{
if(size12)temp=ascii_1206[chr][t]; //调用1206字体
else if(size16)temp=ascii_1608[chr][t]; //调用1608字体
else if(size==24)temp=ascii_2412[chr][t]; //调用2412字体
else return; //没有的字库
for(t1=0;t1<8;t1++)
{
if(temp&0x80)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp<<=1;
y++;
if((y-y0)==size)
{
y=y0;
x++;
break;
}
}
}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;
while(n–)result*=m;
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//num:数值(0~4294967295);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow0&&t<(len-1))
{
if(temp0)
{
OLED_ShowChar(x+(size/2)*t,y,’ ',size,1);
continue;
}else enshow=1;
} OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); }
}
//显示字符串
//x,y:起点坐标
//size:字体大小
//*p:字符串起始地址
void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size)
{
while((*p<=‘~’)&&(*p>=’ '))//判断是不是非法字符!
{
if(x>(128-(size/2))){x=0;y+=size;}
if(y>(64-size)){y=x=0;OLED_Clear();}
OLED_ShowChar(x,y,*p,size,1);
x+=size/2;
p++;
}
}
//显示汉字
//x,y:起点坐标
//pos:数组位置汉字显示
//size:字体大小
//mode:0,反白显示;1,正常显示
void OLED_ShowFontHZ(u8 x,u8 y,u8 pos,u8 size,u8 mode)
{
u8 temp,t,t1;
u8 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数
if(size!=12&&size!=16&&size!=24&&size!=32)return; //不支持的size
for(t=0;t<csize;t++) { if(size==12)temp=FontHzk_12[pos][t]; //调用1206字体 else if(size==16)temp=FontHzk_16[pos][t]; //调用1608字体 else if(size==24)temp=FontHzk_24[pos][t]; //调用2412字体 else if(size==32)temp=FontHzk_32[pos][t]; //调用3216字体 else return; //没有的字库 for(t1=0;t1<8;t1++) { if(temp&0x80)OLED_DrawPoint(x,y,mode); else OLED_DrawPoint(x,y,!mode); temp<<=1; y++; if((y-y0)==size) { y=y0; x++; break; } } }
}
//显示BMP图片128×64
//起始点坐标(x,y),x的范围0~127,y为页的范围0~7
void OLED_DrawBMP(u8 x0, u8 y0,u8 x1, u8 y1,u8 BMP[])
{
u16 j=0;
u8 x,y;
if(y1%8==0)y=y1/8; else y=y1/8+1; for(y=y0;y<y1;y++) { OLED_Set_Pos(x0,y); for(x=x0;x<x1;x++) { OLED_WR_Byte(BMP[j++],OLED_DATA); } }
}
//GND 接电源地
//VCC 接5V或3.3v电源
//D0 接PD6(SCL)
//D1 接PD7(SDA)
//RES 接PD4
//DC 接PD5
//CS 接PD3
void OLED_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
#if OLED_MODE==0 //4线SPI模式
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_6;//管脚设置
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不拉
GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化结构体
GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_6); //拉高电平
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_13;//管脚设置 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不拉 GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化结构体 GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_13); //拉高电平 OLED_Clear();
#endif
#if OLED_MODE==1 //8080模式
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//管脚设置 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化结构体 GPIO_SetBits(GPIOD,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
GPIO_InitStructure.GPIO_Pin = 0XFF; //PC0-7
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,0xFF); //PC0-7输出高
#endif
#if OLED_MODE==2 //IIC模式
#endif
OLED_RST=1; delay_ms(100); OLED_RST=0; delay_ms(100); OLED_RST=1; OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示 OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率 OLED_WR_Byte(80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率 OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数 OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移 OLED_WR_Byte(0X00,OLED_CMD); //默认为0 OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数. OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置 OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭 OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式 OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127; OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置 OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置 OLED_WR_Byte(0x81,OLED_CMD); //对比度设置 OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮) OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期 OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2; OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率 OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 OLED_Clear();
}
#include “oled.h”
#include “oledfont.h”
#include “delay.h”
//OLED的显存
//存放格式如下.
//[0]0 1 2 3 … 127
//[1]0 1 2 3 … 127
//[2]0 1 2 3 … 127
//[3]0 1 2 3 … 127
//[4]0 1 2 3 … 127
//[5]0 1 2 3 … 127
//[6]0 1 2 3 … 127
//[7]0 1 2 3 … 127
u8 OLED_GRAM[128][8];
#if OLED_MODE==0
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{
u8 i;
OLED_DC=cmd;
OLED_CS=0;
for(i=0;i<8;i++)
{
OLED_SCL=0;
if(dat&0x80)
OLED_SDA=1;
else
OLED_SDA=0;
OLED_SCL=1;
dat<<=1;
}
OLED_CS=1;
OLED_DC=1;
}
#endif
#if OLED_MODE==1
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{
OLED_DATA_OUT(dat);
OLED_RST=cmd;
OLED_CS=0;
OLED_WR=0;
OLED_WR=1;
OLED_CS=1;
OLED_DC=1;
}
#endif
#if OLED_MODE==2
void OLED_WR_Byte(u8 dat,u8 cmd)
{
}
#endif
//更新显存到LCD
void OLED_Refresh_Gram(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WR_Byte(0xb0+y,OLED_CMD);
OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD);
}
//开启OLED显示
void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
{
OLED_GRAM[n][i]=0;
}
}
OLED_Refresh_Gram();//更新显示
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
u8 pos,bx,temp=0;
if(x>127||y>63)return;//超出范围了.
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
if(t)OLED_GRAM[x][pos]|=temp;
else OLED_GRAM[x][pos]&=~temp;
}
void OLED_DrawLine(u8 x1, u8 y1, u8 x2, u8 y2)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //计算坐标增量 delta_y=y2-y1; uRow=x1; uCol=y1; if(delta_x>0)incx=1; //设置单步方向 else if(delta_x==0)incx=0;//垂直线 else {incx=-1;delta_x=-delta_x;} if(delta_y>0)incy=1; else if(delta_y==0)incy=0;//水平线 else{incy=-1;delta_y=-delta_y;} if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 else distance=delta_y; for(t=0;t<=distance+1;t++ )//画线输出 { OLED_DrawPoint(uRow,uCol,1);//画点 xerr+=delta_x ; yerr+=delta_y ; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } }
}
void OLED_DrawRectangle(u8 x1, u8 y1, u8 x2, u8 y2)
{
OLED_DrawLine(x1,y1,x2,y1);
OLED_DrawLine(x1,y1,x1,y2);
OLED_DrawLine(x1,y2,x2,y2);
OLED_DrawLine(x2,y1,x2,y2);
}
//x1,y1,x2,y2 填充区域的对角坐标
//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
//dot:0,清空;1,填充
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)
{
u8 x,y;
for(x=x1;x<=x2;x++)
{
for(y=y1;y<=y2;y++)
{
OLED_DrawPoint(x,y,dot);
}
}
OLED_Refresh_Gram();//更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 12/16/24
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{
u8 temp,t,t1;
u8 y0=y;
u8 csize=(size/8+((size%8)?1:0)) * (size/2); //得到字体一个字符对应点阵集所占的字节数
chr=chr-’ ';//得到偏移后的值
for(t=0;t<csize;t++)
{
if(size12)temp=ascii_1206[chr][t]; //调用1206字体
else if(size16)temp=ascii_1608[chr][t]; //调用1608字体
else if(size==24)temp=ascii_2412[chr][t]; //调用2412字体
else return; //没有的字库
for(t1=0;t1<8;t1++)
{
if(temp&0x80)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp<<=1;
y++;
if((y-y0)==size)
{
y=y0;
x++;
break;
}
}
}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;
while(n–)result*=m;
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//num:数值(0~4294967295);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow0&&t<(len-1))
{
if(temp0)
{
OLED_ShowChar(x+(size/2)*t,y,’ ',size,1);
continue;
}else enshow=1;
} OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); }
}
//显示字符串
//x,y:起点坐标
//size:字体大小
//*p:字符串起始地址
void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size)
{
while((*p<=‘~’)&&(*p>=’ '))//判断是不是非法字符!
{
if(x>(128-(size/2))){x=0;y+=size;}
if(y>(64-size)){y=x=0;OLED_Clear();}
OLED_ShowChar(x,y,*p,size,1);
x+=size/2;
p++;
}
}
//显示汉字
//x,y:起点坐标
//pos:数组位置汉字显示
//size:字体大小
//mode:0,反白显示;1,正常显示
void OLED_ShowFontHZ(u8 x,u8 y,u8 pos,u8 size,u8 mode)
{
u8 temp,t,t1;
u8 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数
if(size!=12&&size!=16&&size!=24&&size!=32)return; //不支持的size
for(t=0;t<csize;t++) { if(size==12)temp=FontHzk_12[pos][t]; //调用1206字体 else if(size==16)temp=FontHzk_16[pos][t]; //调用1608字体 else if(size==24)temp=FontHzk_24[pos][t]; //调用2412字体 else if(size==32)temp=FontHzk_32[pos][t]; //调用3216字体 else return; //没有的字库 for(t1=0;t1<8;t1++) { if(temp&0x80)OLED_DrawPoint(x,y,mode); else OLED_DrawPoint(x,y,!mode); temp<<=1; y++; if((y-y0)==size) { y=y0; x++; break; } } }
}
//显示BMP图片128×64
//起始点坐标(x,y),x的范围0~127,y为页的范围0~7
void OLED_DrawBMP(u8 x0, u8 y0,u8 x1, u8 y1,u8 BMP[])
{
u16 j=0;
u8 x,y;
if(y1%8==0)y=y1/8; else y=y1/8+1; for(y=y0;y<y1;y++) { OLED_Set_Pos(x0,y); for(x=x0;x<x1;x++) { OLED_WR_Byte(BMP[j++],OLED_DATA); } }
}
//GND 接电源地
//VCC 接5V或3.3v电源
//D0 接PD6(SCL)
//D1 接PD7(SDA)
//RES 接PD4
//DC 接PD5
//CS 接PD3
void OLED_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
#if OLED_MODE==0 //4线SPI模式
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_6;//管脚设置
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不拉
GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化结构体
GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_6); //拉高电平
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_13;//管脚设置 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//不拉 GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化结构体 GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_13); //拉高电平 OLED_Clear();
#endif
#if OLED_MODE==1 //8080模式
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//管脚设置 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOD,&GPIO_InitStructure); //初始化结构体 GPIO_SetBits(GPIOD,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
GPIO_InitStructure.GPIO_Pin = 0XFF; //PC0-7
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,0xFF); //PC0-7输出高
#endif
#if OLED_MODE==2 //IIC模式
#endif
OLED_RST=1; delay_ms(100); OLED_RST=0; delay_ms(100); OLED_RST=1; OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示 OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率 OLED_WR_Byte(80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率 OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数 OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移 OLED_WR_Byte(0X00,OLED_CMD); //默认为0 OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数. OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置 OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭 OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式 OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127; OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置 OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置 OLED_WR_Byte(0x81,OLED_CMD); //对比度设置 OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮) OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期 OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2; OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率 OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 OLED_Clear();
}
#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 = (840-1); //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=(10-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=14;
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”
__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 = ENABLE;
//禁止外部边沿触发
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
//外部触发通道,本例子使用软件触发,此值随便赋值即可
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
//数据右对齐
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_15Cycles);
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 =6;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void Adc_Init(void)
{
ADC_GPIO_Config();
ADC_Mode_Config();
ADC_NVIC_Config();
}
#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 */
#include “pid.h”
float kp, ki, kd; // PID参数
float last_error = 0,last_error_2 = 0 , last_output, setpoint, input, output;
// 修改pid.c
#define MAX_INTEGRAL 20.0f // 积分限幅
float pid_control(float KP, float KI, float KD, float Set_Point, float Now_Point)
{
static float integral = 0;
float error = Set_Point - Now_Point;
// 积分项限幅 integral += error; if (integral > MAX_INTEGRAL) integral = MAX_INTEGRAL; if (integral < -MAX_INTEGRAL) integral = -MAX_INTEGRAL; float output = KP * error + KI * integral + KD * (error - last_error); last_error = error; // 输出限幅 (0-100%) if (output > 100.0f) output = 100.0f; if (output < 0.0f) output = 0.0f; return output;
} #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 */
最新发布