标题:
基于stm32的spwm输出程序 支持三相,有详细注释
[打印本页]
作者:
852850888
时间:
2018-10-16 17:33
标题:
基于stm32的spwm输出程序 支持三相,有详细注释
这是基于stm32的SPWM输出程序,支持三相,有详细注释。
单片机源程序如下:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "SPWM.h"
#include "stdio.h"
char displayhc[20];
int k=0;
void my_delay_ms(int i)
{
for(;i>0;i--)
{
for(k=0;k<8000;k++)
{
__nop();
}
}
}
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == 1 )
{
// while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == 0);
return 1;
}
else
return 0;
}
#include "oled.h"
extern float pin_lv;
uint8_t key1=1,key2=1,key3=1,key4=1;
int key1_flag=0,key2_flag=0,key3_flag=0,key4_flag=2;
void check_key(void)
{
// key1=Key_Scan(GPIOC,GPIO_Pin_10);
key4=Key_Scan(GPIOC,GPIO_Pin_7);
if(key4==0){my_delay_ms(30);key4=Key_Scan(GPIOC,GPIO_Pin_7);if(key4==0)key4_flag--;if(key4_flag<0)key4_flag=5;}
while(key4==0)key4=Key_Scan(GPIOC,GPIO_Pin_7);
if(Key_Scan(GPIOC,GPIO_Pin_8)==0){my_delay_ms(30);if(Key_Scan(GPIOC,GPIO_Pin_8)==0)
{
if(key4_flag==0)pin_lv=pin_lv+1.0;
if(key4_flag==0)pin_lv=pin_lv-11.0;
if(key4_flag==1)pin_lv=pin_lv-0.1;
if(key4_flag==2)pin_lv=pin_lv-1.0;
if(pin_lv<=20.0)pin_lv=20.0;
TIM4->PSC=1.0/pin_lv/22.2259*10000000.0;
sprintf(displayhc,"%3.1f",pin_lv);
OLED_ShowString(64,6,displayhc);
}
}
while(Key_Scan(GPIOC,GPIO_Pin_8)==0);
if(Key_Scan(GPIOC,GPIO_Pin_9)==0){my_delay_ms(30);if(Key_Scan(GPIOC,GPIO_Pin_9)==0)
{
if(key4_flag==2)pin_lv=pin_lv+1.0;
if(key4_flag==1)pin_lv=pin_lv+0.1;
if(key4_flag==0)pin_lv=pin_lv+10.0;
if(pin_lv>=100.0)pin_lv=100.0;
TIM4->PSC=1.0/pin_lv/22.2259*10000000.0;
sprintf(displayhc,"%3.1f",pin_lv);
OLED_ShowString(64,6,displayhc);
}
}
while(Key_Scan(GPIOC,GPIO_Pin_9)==0);
}
#include "stm32f10x_adc.h"
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_1Cycles5 ); //ADC1,ADC通道,采样时间为1.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
double pid_lim(double x,double max,double min)
{
if(x>max)return max;
if(x<min)return min;
return x ;
}
int test1=0;
int m=0;
long int zhong=0;
int zhi=0;
#include "SPWM.H"
#define guan_xi 20.0
float set_vcc=706;
float p=0.001,i=0,d=0.002;
float err=0,last_err=0,err_sum=0;
float pid_out=0;
u16 acd_veul=0;
int d_fen_pin=0;
void wei_ya_pid()
{
for(i=0;i<100000;i++)
{
acd_veul=Get_Adc(ADC_Channel_2);
zhong+=acd_veul;
}
zhi=zhong/100000;
zhong=0;
// err=702-zhi;
// pid_out=err*p;
// err_sum+=err;
// err_sum=pid_lim(err_sum,100.0,-100.0);
// pid_out+=err_sum*i;
// pid_out+=(err-last_err)*d;
//
// d_fen_pin++;
// if(d_fen_pin%10000)last_err=err;
//
// tiao_fu_sin_1_A(0.9+pid_out);
// tiao_fu_sin_1_C(0.9+pid_out);
if((zhi-set_vcc)>2)pid_out=pid_out-0.006;//
if((zhi-set_vcc)<-2)pid_out=pid_out+0.006;//706
tiao_fu_sin_1_A(0.8+pid_out); //0.9
tiao_fu_sin_1_C(0.8+pid_out);
}
float wei_ding_dian_ya=0;
int mo_shi=0;
float xian_shi_pin_ln=50.1;
float wei_1A=0.878,wei_2A=1.11;
int main(void)
{
TIM_Int_Init();
TIM_PWM_Init();
TIM_Cmd(TIM3, ENABLE); /* TIM3 */
TIM_Cmd(TIM4, ENABLE); /* TIM4 */
Key_GPIO_Config();
Adc_Init();
delay_init(); //延时函数初始化
OLED_Init(); //初始化OLED
OLED_Clear();
mo_shi=2018;
OLED_ShowString(0,0,"2018");
Lcd12864_Write16CnCHAR(32,0,"年电子竞赛");
// Lcd12864_Write16CnCHAR(0,2,"测试模式");
Lcd12864_Write16CnCHAR(0,6,"频率");
// Lcd12864_Write16CnCHAR(0,6,"输出电流");
// sprintf(displayhc,"%d",mo_shi);
// OLED_ShowString(64,2,displayhc);
sprintf(displayhc,"%3.1f",pin_lv);
OLED_ShowString(64,6,displayhc);
//OLED_ShowString(64,4,xian_shi_pin_ln);
// OLED_ShowString(64,6,3);
while (1)
{
check_key();
if(key4_flag==5) { tiao_fu_sin_1_A(wei_1A); tiao_fu_sin_1_C(wei_1A); if(Key_Scan(GPIOC,GPIO_Pin_9)==0){my_delay_ms(30);if(Key_Scan(GPIOC,GPIO_Pin_9)==0)
{
wei_1A=wei_1A+0.0025;
}
}
while(Key_Scan(GPIOC,GPIO_Pin_9)==0);
if(Key_Scan(GPIOC,GPIO_Pin_8)==0){my_delay_ms(30);if(Key_Scan(GPIOC,GPIO_Pin_8)==0)
{
wei_1A=wei_1A-0.0025;
}
}
while(Key_Scan(GPIOC,GPIO_Pin_8)==0);
}
else if(key4_flag==4){ tiao_fu_sin_1_A(wei_2A ); tiao_fu_sin_1_C(wei_2A); if(Key_Scan(GPIOC,GPIO_Pin_9)==0){my_delay_ms(30);if(Key_Scan(GPIOC,GPIO_Pin_9)==0)
{
wei_2A=wei_2A+0.0025;
}
}
while(Key_Scan(GPIOC,GPIO_Pin_9)==0);
if(Key_Scan(GPIOC,GPIO_Pin_8)==0){my_delay_ms(30);if(Key_Scan(GPIOC,GPIO_Pin_8)==0)
{
wei_2A=wei_2A-0.0025;
}
}
while(Key_Scan(GPIOC,GPIO_Pin_8)==0);
}
else
{
// key4_flag=3;
// set_vcc=708;
wei_ya_pid();
}
if(key4_flag==3){
if(Key_Scan(GPIOC,GPIO_Pin_9)==0){my_delay_ms(10);if(Key_Scan(GPIOC,GPIO_Pin_9)==0)
{
// set_vcc=set_vcc+5;
}
}
while(Key_Scan(GPIOC,GPIO_Pin_9)==0);
if(Key_Scan(GPIOC,GPIO_Pin_8)==0){my_delay_ms(10);if(Key_Scan(GPIOC,GPIO_Pin_8)==0)
{
set_vcc=set_vcc-156;
if(set_vcc==550){
Lcd12864_Write16CnCHAR(0,3,"调压到");
sprintf(displayhc,"%3.1f",20.0);
OLED_ShowString(64,3,displayhc);
}
if(set_vcc==394){
sprintf(displayhc,"%3.1f",14.6);
OLED_ShowString(64,3,displayhc);
}
}
}
while(Key_Scan(GPIOC,GPIO_Pin_8)==0){}
}
}
}
复制代码
所有资料51hei提供下载:
spwm例程.rar
(315.11 KB, 下载次数: 234)
2018-10-16 18:07 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
hbthgsli
时间:
2019-5-14 06:42
好人呀!谢谢!好资料,51黑有你更精彩!!!
作者:
aaaaaa。
时间:
2019-5-19 10:57
我有点不太懂,SPWM波用示波器看是方波还是正弦波?还有那个SPWM生成软件中的调度比怎么来的?以及幅值、 中值该为多少
作者:
aaaaaa。
时间:
2019-5-20 19:49
好人呀,谢谢
作者:
蛋卷卷
时间:
2019-7-14 16:47
aaaaaa。 发表于 2019-5-19 10:57
我有点不太懂,SPWM波用示波器看是方波还是正弦波?还有那个SPWM生成软件中的调度比怎么来的?以及幅值、 ...
经过滤波器就是正弦波了,不过你得焊个
作者:
v帆帆帆帆
时间:
2019-7-17 09:28
不错不错
作者:
杨永超
时间:
2019-7-19 22:09
为什么我下载了不是文件,,而是一个打不开的文档
作者:
bigbody1026
时间:
2019-7-20 12:53
我有点不太懂,SPWM波用示波器看是方波还是正弦波?还有那个SPWM生成软件中的调度比怎么来的?以及幅值、 中值该为多少
作者:
robot9527
时间:
2019-7-20 16:15
很实用的资料,学习一下!谢谢楼主分享!
作者:
Gavin.Tong
时间:
2019-7-23 16:19
有没有电路图
作者:
18172467016
时间:
2019-7-23 21:08
好资料,51黑有你更精彩!!!
作者:
hong19851024
时间:
2019-8-28 14:04
好资料,51黑有你更精彩!!!
作者:
13825283634
时间:
2019-8-28 16:59
感谢,51黑有你更精彩!!!
作者:
waronder
时间:
2019-9-20 14:52
好东西当然要支持,谢谢分享呀!
作者:
ovanl111
时间:
2025-7-28 15:45
感谢,51黑有你更精彩!!!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1