微软公司宣布不再支持你正在使用的 IE浏览器,这会严重影响浏览网页,请使用微软最新的Edge浏览器
您好, 登录| 注册|

上传一份完整的SPWM code in C,旨在提高国人的设计水平

  • 2006-04-24 23:39
  • zack

    LV.0
  • 5.3w

    浏览

  • 259

    回复

  • 4

    获赞

  • /*****************************************************************************
    * Filename: MAIN.C
    ******************************************************************************
    *
    * Author: Dave Karipides
    * Company: APS, Inc.
    * Date: 3-3-97
    * Compiled Using MPLAB-C Rev 1.21
    *
    ******************************************************************************

    ******************************************************************************
    *
    * Description: The main routine calls all the functions for generating
    * an OPEN_LOOP or FEEDBACK sine wave of either 50 or 60 Hz.
    *
    ******************************************************************************
    *

    *
    *
    ******************************************************************************/

    /*****************************************************************************
    * main()
    *
    * Description: The main routine initializes the registers and loops
    * forever.  All control is handled in the TMR0 INT
    * routine.
    *
    *
    * Input Variables: NONE
    *
    * Output Variables: NONE
    *
    *
    ******************************************************************************/

    //#define OPEN_LOOP
    #define FEEDBACK
    //#define 50Hz
    #define 60Hz

    #pragma option v
    #include <17c43.h>
    #include
    #include

    #ifdef OPEN_LOOP
    // This table yields Full VRMS input
    unsigned char const pwmtab[32]={0,25,50,74,98,120,142,162,180,197,212,
    225,235,244,250,254,255,254,250,244,235,
    225,212,197,180,162,142,120,98,74,50,25};
    #endif
    #ifdef FEEDBACK
    // This table yields slightly less than Full VRMS input
    unsigned char const pwmtab[32]={0,20,40,60,79,97,114,131,145,159,171,
    181,189,197,202,205,206,205,202,197,189,
    181,171,159,145,131,114,97,79,60,40,20};
    #endif

    long read_ad(unsigned char); // Prototype for A/D converter function

    unsigned char index; // Index into the sinewave reference table
    unsigned char sign; // Flag used to unfold sinewave reference table
    long reference; // Value of the sinewave refrence after unfolding
    unsigned char reference_lo  @ reference; // V1.21 of Compiler does not type cast unsigned
    // char to long so we will write to low byte separately
    long out_volt; // Magnitude of the output voltage;
    long y; // Variables used in compensation routine
    long yold;
    long x;
    long xold;
    long ad_value; // A/D Converter Value

    void main(void)
    {
    CLRWDT();
    PORTC = 0; // Zero out portc latches
    DDRC = 0x22; // Set up Data direction register for C
    DDRB = 0; // Set up Data direction register for B
    PR1 = 0xFF; // Setup PR1 register (24.4Khz @ 25Mhz clk)
    PW1DCL = 0; // Set low bits of PWM to 0
    PW1DCH = 0; // Init PWM duty cycle to 0

    T0STA = 0x20; // Configure Timer0 prescaler
    INTSTA.T0IE = 1; // Enable Timer 0 interrupt
    TCON1.TMR1CS = 0;
    TCON1.T16 = 0;
    TCON2.TMR1ON = 1; // Start timer 1 (PWM timer)
    TCON2.PWM1ON = 1; // Turn on the PWM
    CPUSTA.GLINTD = 0; // Unmask the interrupts

    index = 0; // Initialize variables
    sign = 0;
    y = 0;
    yold = 0;
    x = 0;
    xold = 0;
    PORTC.0 = 1; // Enable the Inverter
    while(1); // Loop forever, execute in INT Routine
    }

    #ifdef FEEDBACK
    __TMR0() // Timer  interrupt
    {
    T0STA.T0CS = 0; // Stop timer
    PORTB.7=1;
    #ifdef 60Hz
    TMR0L=0xA5;
    TMR0H=0xF9; // Make Timer0 interrupt at 3.84KHz for 60Hz output
    #endif
    #ifdef 50Hz
    TMR0L=0x5F; // Make Timer0 interrupt at 3.20KHz for 50Hz output
    TMR0H=0xF8;
    #endif
    T0STA.T0CS = 1; // Start timer
    CLRWDT();

    reference = 0; // Clear Reference Value
    reference_lo = pwmtab[index]; // Lookup the value of the sinewave reference

    if (!index) // Toggle Sign Every Cycle Through table
    sign = ~sign;
    ++index; // Increment index
    if (index == 32) // If end of table, reset counter
    index = 0;
    if (sign) // If negative going wave
    {
    reference = ~reference; // V1.21 of Compiler negate (-ref) doesn't work for
    reference = reference + 1;// ref<=0
    }
    ad_value = read_ad(0);
    out_volt = ad_value - 512; // Read output voltage (512 counts=0 volts out)

    // Form the expression y = yold + (0.09261 * (x + xold))
    // Where yold, xold is the value of y, x from the previous sample
    // x is the , formed by the difference between the output
    // of the inverter and the reference signal.
    x = out_volt - reference;
    y = ((x + xold) * 24);
    y = y / 256;
    y = y + yold;
    if (y >= 0)
    {
    PORTC.2 = 0; // Set positive going cycle
    } else
    {
    PORTC.2 = 1; // Set negative going cycle
    y = ~y;
    y = y + 1;
    }
    if (y > 255)
    y = 255; // Limit y
    PW1DCH = y; // Update duty cycle
    xold = x; // Store previous sample's state
    yold = y;
    PORTB.7=0;
    }
    #endif

    #ifdef OPEN_LOOP
    // The inverter runs in an open loop mode with OPEN_LOOP defined.
    __TMR0() // Timer interrupt
    {
    T0STA.T0CS = 0; // Stop timer
    #ifdef 60Hz
    TMR0L=0xA5;
    TMR0H=0xF9; //Make Timer0 interrupt at 3.84KHz for 60Hz output
    #endif
    #ifdef 50Hz
    TMR0L=0x5F; //Make Timer0 interrupt at 3.20KHz for 50Hz output
    TMR0H=0xF8;
    #endif
    T0STA.T0CS=1; //Start timer
    CLRWDT();

    PW1DCH = pwmtab[index];
    if (!index)
    {
    PORTC.0 = 0; // Gate Drive off
    PORTC.2 = ~PORTC.2; // Flip Pos/Neg bit
    PORTC.0 = 1; // Gate Drive on
    }
    ++index;
    if (index == 32)
    index = 0;
    PORTC.3 = ~PORTC.3; // Toggle bit to test freq.
    }
    #endif

    long read_ad(unsigned char channel)
    {
    long result;

    PORTC.6 = 1; // Write bit high
    PORTC.7 = 1; // Read bit high
    PORTC.4 = 1; // Chip select high
    DDRD = 0; // Make PORTD an output
    PORTD = 0x04; // Single ended mode signed 10 bit chan 0 Right justified
    PORTC.4 = 0; // Select chip
    PORTC.6 = 0; // latch command word int A/D
    PORTC.6 = 1; // Start conversion
    PORTC.4 = 1; // Deselect chip
    while (PORTC.5); // Wait for conversion to complete
    DDRD = 0xFF; // Make PORTD an input
    PORTC.4 = 0; // Select chip
    PORTC.7 = 0; // Read high byte
    *( ((unsigned char*)&result) + 1) = PORTD;
    PORTC.7 = 1;
    PORTC.4 = 1;
    PORTC.4 = 0;
    PORTC.7 = 0; // Read low byte
    *( ((unsigned char*)&result) ) = PORTD;
    PORTC.7 = 1;
    PORTC.4 = 1; // Reset chip select lines
    return (result); // Return data
    }

    同是电子工程师,请一定不要吝啬你的赞!

    4人已赞

    编辑 举报

    LV.1

    647433

    84658

    13

    40850

    说说你的看法

  • LV.

    @

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    取消
    发送
  • 现在还没有回复呢,说说你的想法

    现在还没有回复呢,说说你的想法

    全部回复(259)

  • zack

    LV.1

    2006-05-13 07:55

    @xikun

    谢谢您了,怎么下载不了?
    没办法,老师指定要用80c196mc的,本来我也是想用dsp的,可是最后还是要按老师的要求做.
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647470

    84658

    13

    40850

    取消
    发送
    32
  • zack

    LV.1

    2006-05-15 10:48

    @zack


    2KW容量,空载电流达0.48A

    有效地控制MOSFET的尖峰脉冲.
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647464

    84658

    13

    40850

    取消
    发送
    33
  • xzszrs

    LV.1

    2006-05-19 14:02

    @zack


    这是我公司做的两台EPS样机,都已经过严格测试,性能价格相对与同类产品都有优势,更重要的是我们有独立的开发创新能力,可以随时不断地对产品系统优化升级!
    目前,公司很小,但我们这里汇集了一批优秀尽业的软硬件工程师、结构工程师等等年轻人.我们希望与一些大公司合作电源项目的生产和研发,我们公司负责产品的研发、生产、管理.母公司只负责品牌和销售,我们双方互惠互利达到共赢的发展目的.欢迎实地考察.
    有意想的请与我联系:QQ :27579653
    zack!了不起!顶!
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647474

    84658

    13

    70075

    取消
    发送
    34
  • zack

    LV.1

    2006-05-19 22:16

    @xzszrs

    zack!了不起!顶!
    谢谢,xzszrs你很了不呀. 有很多电源方面的东西想和你共同合作开发呢.相互学习、批评指正、共同发展!
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647475

    84658

    13

    40850

    取消
    发送
    35
  • zack

    LV.1

    2006-05-20 00:15

    @

    这么好的思路和参考模型咋就回帖的朋友这么少呢?
    好吧.就把它翻一点吧.希望我抛砖引玉的想法不要落空.
    也希望得到一点感觉的朋友发表一下意见OK?WELL,LET'S GO!

    /*****************************************************************************
    * Filename: MAIN.C
    ******************************************************************************
    *
    * Author: Dave Karipides
    * Company: APS, Inc.
    * Date: 3-3-97
    * Compiled Using MPLAB-C Rev 1.21
    *       编译平台:MAPLAB-C Rev1.21(我用HT-PICC9.05L)
    ******************************************************************************

    ******************************************************************************
    *
    * Description: The main routine calls all the functions for generating
    * an OPEN_LOOP or FEEDBACK sine wave of either 50 or 60 Hz.
    *       软件描述:主程序调用函数产生开环和闭环调节的正弦波可设置50HZ或60HZ  
    ******************************************************************************
    *

    *
    *
    ******************************************************************************/

    /*****************************************************************************
    * main()
    *
    * Description: The main routine initializes the registers and loops
    * forever.  All control is handled in the TMR0 INT
    * routine.
    *       主程序描述:主程序初始化个积存器组后台循环.所有控制操作在TMRO中断子程序处理.
    *
    * Input Variables: NONE
    *       输入变量:没有
    * Output Variables: NONE
    *       输出变量:没有
    *
    ******************************************************************************/

    //#define OPEN_LOOP
    #define FEEDBACK
    //#define 50Hz
    #define 60Hz

    #pragma option v
    #include <17c43.h>
    #include
    #include

    #ifdef OPEN_LOOP          
    // This table yields Full VRMS input 最大额定电压输入表,测试用
    unsigned char const pwmtab[32]={0,25,50,74,98,120,142,162,180,197,212,
    225,235,244,250,254,255,254,250,244,235,
    225,212,197,180,162,142,120,98,74,50,25};
    #endif
    #ifdef FEEDBACK
    // This table yields slightly less than Full VRMS input 调节电压输入表
    unsigned char const pwmtab[32]={0,20,40,60,79,97,114,131,145,159,171,
    181,189,197,202,205,206,205,202,197,189,
    181,171,159,145,131,114,97,79,60,40,20};
    #endif

    long read_ad(unsigned char); // Prototype for A/D converter function声明A/D采样函数

    unsigned char index; // Index into the sinewave reference table查表顺序寄存器
    unsigned char sign; // Flag used to unfold sinewave reference table正弦表输出标志
    long reference; // Value of the sinewave refrence after unfolding输出电压参考值
    unsigned char reference_lo  @ reference; // V1.21 of Compiler does not type cast unsigned
    // char to long so we will write to low byte separately把电压的低位字节定义在电压寄存器的低位字节
    long out_volt; // Magnitude of the output voltage;输出电压大小
    long y; // Variables used in compensation routine;电压补偿子程序所用的变量
    long yold;
    long x;
    long xold;
    long ad_value; // A/D Converter Value;AD转换数值寄存器

    void main(void)
    {
    CLRWDT();//清看门狗,一般PIC初始化之前需要加次命令,以免不必要的中断
    PORTC = 0; // Zero out portc latches;C端口积存器清零
    DDRC = 0x22; // Set up Data direction register for C;PORTC端口方向积存器定义
    DDRB = 0; // Set up Data direction register for B;PORTB端口方向积存器定义
    PR1 = 0xFF; // Setup PR1 register (24.4Khz @ 25Mhz clk)设置PWM频率在25MHZ时,PR1=0XFF,则PWM频率为24.4KHZ.具体计算见手册
    PW1DCL = 0; // Set low bits of PWM to 0
    PW1DCH = 0; // Init PWM duty cycle to 0;初始化占空比为零

    T0STA = 0x20; // Configure Timer0 prescaler;设置定时期T0预分频
    INTSTA.T0IE = 1; // Enable Timer 0 interrupt;开定时器TO中断
    TCON1.TMR1CS = 0;
    TCON1.T16 = 0;
    TCON2.TMR1ON = 1; // Start timer 1 (PWM timer);开定时器T1
    TCON2.PWM1ON = 1; // Turn on the PWM,开定TMR2,PWM输出
    CPUSTA.GLINTD = 0; // Unmask the interrupts;开所有中断

    index = 0; // Initialize variables;个变量初始化
    sign = 0;
    y = 0;
    yold = 0;
    x = 0;
    xold = 0;
    PORTC.0 = 1; // Enable the Inverter;PORTC.0逆变允许开关,允许输出
    while(1); // Loop forever, execute in INT Routine;前台循环等待中断.......
    }

    #ifdef FEEDBACK//预编译命令,反馈闭环情况下TMRO中断处理.
    __TMR0() // Timer  interrupt
    {
    T0STA.T0CS = 0; // Stop timer
    PORTB.7=1;
    #ifdef 60Hz
    TMR0L=0xA5;
    TMR0H=0xF9; // Make Timer0 interrupt at 3.84KHz for 60Hz output
    #endif
                                             TMRO每0.26ms中断一次,0.26*32=8.333...ms,为60HZ半周
    #ifdef 50Hz
    TMR0L=0x5F; // Make Timer0 interrupt at 3.20KHz for 50Hz output
    TMR0H=0xF8;                      TMR0每0.3125ms中断一次,0.3125*32=10ms,为50HZ半周
    #endif
    T0STA.T0CS = 1; // Start timer开定时器件
    CLRWDT();//清看门狗,防止死机

    reference = 0; // Clear Reference Value清除参考电压
    reference_lo = pwmtab[index]; // Lookup the value of the sinewave reference;查表,得到标准参考电压表数据,用于采样比较

    if (!index) // Toggle Sign Every Cycle Through table;每一次查表循环完毕标志取反,用以确定正负半周波形
    sign = ~sign;
    ++index; // Increment index;正弦表顺序取值
    if (index == 32) // If end of table, reset counter;32个点查完后清index
    index = 0;
    if (sign) // If negative going wave;假如正输出负半周波形
    {
    reference = ~reference; // V1.21 of Compiler negate (-ref) doesn't work for
    reference = reference + 1;// ref<=0 ;C编译器版本不同此运算不同
    }
    ad_value = read_ad(0);采样RA0端口数值,也即32个中断采样输出电压,就是半周取32个电压输出点.
    out_volt = ad_value - 512; // Read output voltage (512 counts=0 volts out)采样输出电压在512=0.

    // Form the expression y = yold + (0.09261 * (x + xold));根据PID简化公式稳定调节输出电压
    // Where yold, xold is the value of y, x from the previous sample;yold,xold为前次采样到的y,x值
    // x is the , formed by the difference between the output;X为偏差信号,由输出电压波动数值和参考电压的差值来确定
    // of the inverter and the reference signal.
    x = out_volt - reference;//x等于当前输出电压(有AD采样得到)减取参考电压
    y = ((x + xold) * 24);//
    y = y / 256;//即简化计算0.09261 * (x + xold)
    y = y + yold;//逼近
    if (y >= 0)
    {
    PORTC.2 = 0; // Set positive going cycle;控制正半周输出
    } else
    {
    PORTC.2 = 1; // Set negative going cycle;控制负半周输出
    y = ~y;
    y = y + 1;
    }
    if (y > 255)
    y = 255; // Limit y;限制Y最大数值,不限制会益处复位,输出电压数值波形重创.
    PW1DCH = y; // Update duty cycle更新
    xold = x; // Store previous sample's state保存当前采样数值
    yold = y;
    PORTB.7=0;
    }
    #endif
    //采用开环输出方案,一般作测试用
    #ifdef OPEN_LOOP
    // The inverter runs in an open loop mode with OPEN_LOOP defined.
    __TMR0() // Timer interrupt
    {
    T0STA.T0CS = 0; // Stop timer
    #ifdef 60Hz
    TMR0L=0xA5;
    TMR0H=0xF9; //Make Timer0 interrupt at 3.84KHz for 60Hz output
    #endif
    #ifdef 50Hz
    TMR0L=0x5F; //Make Timer0 interrupt at 3.20KHz for 50Hz output
    TMR0H=0xF8;
    #endif
    T0STA.T0CS=1; //Start timer
    CLRWDT();

    PW1DCH = pwmtab[index];
    if (!index)
    {
    PORTC.0 = 0; // Gate Drive off
    PORTC.2 = ~PORTC.2; // Flip Pos/Neg bit
    PORTC.0 = 1; // Gate Drive on
    }
    ++index;
    if (index == 32)
    index = 0;
    PORTC.3 = ~PORTC.3; // Toggle bit to test freq.
    }
    #endif

    long read_ad(unsigned char channel)//读AD,CHIP
    {
    long result;

    PORTC.6 = 1; // Write bit high
    PORTC.7 = 1; // Read bit high
    PORTC.4 = 1; // Chip select high
    DDRD = 0; // Make PORTD an output
    PORTD = 0x04; // Single ended mode signed 10 bit chan 0 Right justified
    PORTC.4 = 0; // Select chip
    PORTC.6 = 0; // latch command word int A/D
    PORTC.6 = 1; // Start conversion
    PORTC.4 = 1; // Deselect chip
    while (PORTC.5); // Wait for conversion to complete
    DDRD = 0xFF; // Make PORTD an input
    PORTC.4 = 0; // Select chip
    PORTC.7 = 0; // Read high byte
    *( ((unsigned char*)&result) + 1) = PORTD;
    PORTC.7 = 1;
    PORTC.4 = 1;
    PORTC.4 = 0;
    PORTC.7 = 0; // Read low byte
    *( ((unsigned char*)&result) ) = PORTD;
    PORTC.7 = 1;
    PORTC.4 = 1; // Reset chip select lines
    return (result); // Return data
    }
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647476

    84658

    13

    40850

    取消
    发送
    36
  • nita

    LV.1

    2006-05-21 16:00

    @

    pic17c43的资料吧
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647480

    84658

    13

    2499

    取消
    发送
    37
  • zack

    LV.1

    2006-05-21 18:03

    @nita

    pic17c43的资料吧
    sine波输出的算法.基于PIC16系列的ups控制核心.
    有些朋友对于MCU或DSP产生正弦波的算法没接触过,在此供大家思考!
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647481

    84658

    13

    40850

    取消
    发送
    38
  • qhl0222_cn

    LV.1

    2006-05-25 17:21

    @zack

    80c196mc已经是过时的产品了.现在的电机专用MCU 如 MOTOROLA MR系列,PIC 的dsPIC30F系列,TI的的DSP等等功能不知道强多少而且开发方便.现在学校里都是老的教材,学学基本原理还可以,要跟得上新一点点的技术就不行了.现在大学就这样,没办法,还是要靠自己啊.!
    给你一份资料看看,我想很有帮助哦.
    1147370266.pdf
    为啥下载不了?
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647471

    84658

    13

    99062

    取消
    发送
    39
  • 张无极

    LV.1

    2006-05-28 07:07

    @

    照抄了MICROCHIP公司的源代码,其实源代码里有很多缺陷.并且现在如果做大功率的,则没有人使用这种程序了,属于比较原始的,相当于10年前的水平.
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647482

    84658

    13

    13170

    取消
    发送
    40
  • zack

    LV.1

    2006-05-28 08:56

    @张无极

    照抄了MICROCHIP公司的源代码,其实源代码里有很多缺陷.并且现在如果做大功率的,则没有人使用这种程序了,属于比较原始的,相当于10年前的水平.
    1,请问缺陷在什么地方,请说明,1,2,3,4.
    2,的确这是MICROCHIP的部分代码,我不知道你所谓照抄是什么意思?
      就直接拿来用就可以吗?
    3,所谓相当于10前的水平,现在的水平是什么样的?不要看到DATA 3-3-97,心里就这么浮躁了.
    4,一种算法的借鉴思路是要我们领会之后灵活运用的,不动动脑子是不
      会有长进的.
    5,有比半波实时采样更先进的PID算法,你也要那出来说啊!否着那是放
      屁了.
    呵呵......
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    647483

    84658

    13

    40850

    取消
    发送
    41
  • 现在还没有回复呢,说说你的想法

     1 2 3 4 5 6 7 8 9  
  • 回复

  • 收藏

  • 点赞

  • 举报有害信息

  • 已超出发布时间24小时,无法编辑与删除
    关于我们 联系方法 广告服务 会议服务 电子星球APP 网站地图 不良信息举报 热线:400-003-2006
    © 2002-2023 Netbroad(网博互动)公司版权所有 津ICP备 11006234号-2 联网备案号:12010402000747 增值电信业务经营许可证:津B2-20120058