单位的项目,要求变频、变压。用来驱动高压变压器,做绝缘测试使用。上位机软件通过串口控制升压过程。
废话不多说!先上原理图!不知道如何转图片,只能传文件了。
再来两张印版的照片吧!
正面
背面
焊接完毕的
接下来是源码,采用的MCU是C8051F120相中的是控制简单(PCA模块),速度够快(100Mhz主频,SPWM分辨率可以达到12位)。
/* 使用外部晶振22.1184MHz 方便串口通讯 用PLL 4.5倍频于99.5328MHz PCA0十六位PWM方式 中断中将计算好的初值加0xF000赋予捕捉模块 计数器赋初值0xF000 作为十二位PWM使用 载频24.3kHz M_min = 0.? M_max = 0.9514 */ #include#include #include #include #include #define PI 3.1415926 // π #define Carrier 24300 // 载波载频 #define SYSCLK 99532800L // 晶振频率 #define BAUDRATE 115200 // 波特率 #define value 4096 // 载波周期计数器值 unsigned int *point_sin; // 数组指针 unsigned int frequency = 50; // 调制波频率 unsigned int j; // 用于操作数组 unsigned int reload; // PCA0重载值 unsigned int ISR_time; // 中断计数 unsigned int finish; // 调制波半周期载波个数 float M = 0.9; // 调制比(输出电压) unsigned char data *s,receive[15],volt[6],freq[6]; // 接收电压、频率字符串 unsigned int xdata sin_list[4095]; // 用于存放计算好的计数器初值 bit Isr_flag; // 发生重载标志 bit Fun_flag; // 调制波半周期到标志 bit String_flag; // 串口接收到新参数标志 sbit funwave = P0^3; // 基波 sbit btlamp = P0^5; // 呼吸灯 void OSCILLATOR_Init (void); void PORT_Init (void); void PCA0_Init (void); void CALCULATE (void); void UART1_Init (void); void Timer2_Init(void); void main() { WDTCN = 0xde; WDTCN = 0xad; OSCILLATOR_Init (); PORT_Init (); CALCULATE (); reload = sin_list[0]; PCA0_Init (); UART1_Init (); Timer2_Init(); EA = 1; CR = 1; while(1) { if(String_flag) { String_flag = 0; s = strtok(receive,"@"); strcpy(volt,s); s = strtok(NULL,"@"); strcpy(freq,s); memset(receive,0,15); M = atof(volt); frequency = atoi(freq); CALCULATE (); } if(Isr_flag) { Isr_flag = 0; j++; if(j < finish) reload = sin_list[j]; else { j = 0; reload = sin_list[j]; } } if(Fun_flag) { Fun_flag = 0; funwave = ~funwave; } } } void CALCULATE (void) // 实时计算各交点sin值 装入数组 { unsigned int i; static unsigned int median,surplus; finish = (Carrier/frequency) >> 1; point_sin = &sin_list[0]; median = value * sin(PI * (finish * 2 - 1)/(finish * 2)) * M; surplus = (value - median) >> 1; for(i=1; i<2 * finish; i+=2) { median = value * sin(PI * i / finish / 2) * M; if(median > 4066) median = 4066; *point_sin = surplus + 0xF000 + (value - median) / 2; surplus = (value - median) >> 1; point_sin++; } } void OSCILLATOR_Init (void) // 使用外部晶振22.1184MHz 4.5倍频 锁定在99.5328MHz { unsigned int i; char SFRPAGE_SAVE = SFRPAGE; SFRPAGE = CONFIG_PAGE; OSCICN = 0x80; CLKSEL = 0x00; OSCXCN = 0x67; for (i=0; i < 256; i++); while (!(OSCXCN & 0x80)); SFRPAGE = LEGACY_PAGE; FLSCL |= 0x30; if(SYSCLK <= 25000000) FLSCL &= ~0x30; else if(SYSCLK <= 50000000) FLSCL &= ~0x20; else if(SYSCLK <= 75000000) FLSCL &= ~0x10; else FLSCL &= ~0x00; SFRPAGE = PLL0_PAGE; PLL0CN = 0x04; PLL0CN |= 0x01; PLL0DIV = 0x02; PLL0FLT &= ~0x0f; PLL0FLT |= 0x07; PLL0FLT &= ~0x30; PLL0FLT |= 0x00; PLL0MUL = 0x09; for (i = 0; i < 256; i++) ; PLL0CN |= 0x02; while (PLL0CN & 0x10 == 0x00); SFRPAGE = CONFIG_PAGE; CLKSEL = 0x02; SFRPAGE = SFRPAGE_SAVE; } void PORT_Init (void) { char SFRPAGE_save = SFRPAGE; SFRPAGE = CONFIG_PAGE; XBR0 = 0x08; XBR1 = 0x00; XBR2 = 0x44; P0MDOUT |= 0xFF; SFRPAGE = SFRPAGE_save; } void PCA0_Init (void) { char SFRPAGE_save = SFRPAGE; SFRPAGE = PCA0_PAGE; PCA0CN = 0x00; PCA0MD = 0x09; PCA0CPM0 = 0xC2; PCA0H = 0xF0; PCA0CPL0 = (reload & 0x00FF); PCA0CPH0 = (reload & 0xFF00)>>8; SFRPAGE = CONFIG_PAGE; EIE1 |= 0x08; EIP1 |= 0x08; SFRPAGE = SFRPAGE_save; } void UART1_Init (void) { char SFRPAGE_SAVE = SFRPAGE; SFRPAGE = UART1_PAGE; SCON1 = 0x10; SFRPAGE = TIMER01_PAGE; TMOD &= ~0xF0; TMOD |= 0x20; if(SYSCLK/BAUDRATE/2/256 < 1) { TH1 = -(SYSCLK/BAUDRATE/2); CKCON |= 0x10; } else if (SYSCLK/BAUDRATE/2/256 < 4) { TH1 = -(SYSCLK/BAUDRATE/2/4); CKCON &= ~0x13; CKCON |= 0x01; } else if (SYSCLK/BAUDRATE/2/256 < 12) { TH1 = -(SYSCLK/BAUDRATE/2/12); CKCON &= ~0x13; } else { TH1 = -(SYSCLK/BAUDRATE/2/48); CKCON &= ~0x13; CKCON |= 0x02; } TL1 = TH1; TR1 = 1; EIE2 = 0x40; // 允许中断 SFRPAGE = SFRPAGE_SAVE; } void Timer2_Init(void) { char SFRPAGE_SAVE = SFRPAGE; SFRPAGE = TMR2_PAGE; TMR2CN = 0x04; // 自动重装模式并启动 ET2 = 1; // 中断使能 SFRPAGE = SFRPAGE_SAVE; } void Timer2_ISR (void) interrupt 5 { static unsigned char i; TF2 = 0; if(i < 63) i++; else { btlamp = ~btlamp; i = 0; } } void PCA0_ISR (void) interrupt 9 { CF = 0; PCA0H = 0xF0; PCA0CPL0 = (reload & 0x00FF); PCA0CPH0 = (reload & 0xFF00)>>8; if(!j) Fun_flag = 1; Isr_flag = 1; } void UART1_Interrupt (void) interrupt 20 { static char i; if(RI0) { RI0 = 0; if(SBUF0 == '!') { i = 0; String_flag = 1; } else { receive[i] = SBUF0; i++; } } if(TI0) TI0 = 0; }
通讯格式为A(浮点数)+@(固定)+B(整数)+!(固定)
例如:0.9@50! 表示输出调制比为0.9(如果母线电压为310V输出大概为200V)输出频率为50Hz
波形待续……(主要还是想看看热度)
继续中……
这是串口助手,大家应该不陌生。
0.1@50!
0.3@50!
0.5@50!
0.9@50!
0.9@10!
0.9@20!
0.9@300!
以上波形测得条件为:其中一路SPWM输出,串接5.1K电阻、104电容到地
下面是PCB文件,及简图。
待桥电路搭建完成后,再继续上完整的正弦波形图。
(未完待续…………)