搜索
bottom↓
回复: 9

有人在用595扩展pwm信号吗?谁有思路?指教一二!

[复制链接]

出0入0汤圆

发表于 2012-11-20 18:29:23 | 显示全部楼层 |阅读模式
有人在用595扩展pwm信号吗?谁有思路?指教一二!我看见一个舵机驱动板有32路pwm输出,问了老板,他说是用595在扩展pwm输出,不知道他是不是用的专业pwm芯片。想不通是什么原理。请大神指教一下!他的地址:http://item.taobao.com/item.htm? ... p;cm_id=&pm_id=

先声明本人绝不是做广告的,广告者死光!谢谢大家指点!还有谁有pudn的账号帮忙下了看看呢?感谢!
http://www.pudn.com/downloads149 ... d/detail643936.html

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2012-11-20 18:32:19 | 显示全部楼层
自己先顶一个!大家共同讨论进步,谢谢!

出0入42汤圆

发表于 2012-11-20 19:12:33 | 显示全部楼层
常见舵机,PWM频率很低。用595搞没啥问题。

一般就是MCU+一堆595.

出0入0汤圆

 楼主| 发表于 2012-11-20 19:33:01 | 显示全部楼层
有资料给点看看吗?谢谢了。

出0入0汤圆

发表于 2012-11-20 19:44:38 | 显示全部楼层
jiang887786 发表于 2012-11-20 19:33
有资料给点看看吗?谢谢了。

模拟舵机频率超级低

只是用595扩展io而已。由于频率低,就用定时器做都没问题。

出0入0汤圆

 楼主| 发表于 2012-11-20 19:58:44 | 显示全部楼层
那么占空比很好做吗?如果想做占空比0-99%,可以做到吗?

出0入0汤圆

发表于 2012-11-20 20:54:55 | 显示全部楼层
没有问题的啊,只不过是通过复杂点的程序控制595输出的状态,频率没有直接单片机IO那么快而已,而且595可以支持很高的频率,如果用FPGA,可以做得比单片机的PWM好

出0入0汤圆

 楼主| 发表于 2012-11-21 22:03:53 | 显示全部楼层
,你们都说简单,可我比较菜啊,谁能说说思路啊?我发现了一个飞思卡尔的单片机程序是用定时器模拟的pwm不知道怎么样,程序我贴一下不知道篇幅够不够。
#include <hidef.h>      /* common defines and macros */
#include <MC9S12XEP100.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12xep100"

#define ECT_OC7D_OC7D4_MASK 16   // ??? not defined in library in CW 4.7 ???

//******************************************************************************
// This software is classified as Engineering Sample Software.               
//******************************************************************************
// - OSCILLATOR = 16MHz
// - BUS CLOCK = 25 MHz
// - the sample software does:
// - It generates periodic signal on the port PT4 with variable frequency and stop and start feature
//
//******************************************************************************
// DEFINITIONS
//******************************************************************************
#define     UBYTE       unsigned char
#define     SBYTE                char
#define     UWORD       unsigned  int
#define     SWORD                 int
#define     ULONG       unsigned  long
#define     SLONG                 long
//******************************************************************************
// FUNCTION PROTOTYPES
//******************************************************************************
#define     BUSCLK      25000 // [kHz]
//******************************************************************************
// FUNCTION PROTOTYPES
//******************************************************************************
static void PLL_Init(UBYTE synr, UBYTE refdv, UBYTE postdiv);

void TimerSetup(void);
void startOutputSignal_on_PT4(void);
void stopOutputSignal_on_PT4(void);
void permanent_1_on_PT4(void);
void changePeriod(ULONG per_us);            // input parameter = required period in us
void changeDuty(UWORD duty);        // duty cycle = 0~period (period is calculated global variable)
                                            // IOW it is value of period register TC7

//******************************************************************************
static UWORD period;
//******************************************************************************
// void main(void)
//******************************************************************************
void main(void)
{
  ULONG i;
  UWORD j;
  //----------------------------------------
  ECLKCTL_NECLK = 0;                           // see bus clock on PE4
  //----------------------------------------
  // set 25MHz bus clock from 16MHz OSCCLK // PLL_Init(SYNR;REFDV;POSTDIV)
  PLL_Init(0xD8,0x07,0x01);
  //----------------------------------------
  // - The 1 MHz frequency is generated by means of Main Timer counter in the underflow interrupt by toggling required port.
  //   Generated on the port PT4.
  TimerSetup();
  //----------------------------------------
  startOutputSignal_on_PT4();
  for(;;)
    {
     changePeriod(10000); //10ms
     changeDuty(period/2);

     for(i=0;i<0x1FFFFF;i++) asm nop;        // SW delay
     stopOutputSignal_on_PT4();
     for(i=0;i<0x1FFFFF;i++) asm nop;        // SW delay
     startOutputSignal_on_PT4();
     for(i=0;i<0x1FFFFF;i++) asm nop;        // SW delay
     permanent_1_on_PT4();
     for(i=0;i<0x1FFFFF;i++) asm nop;        // SW delay
     changePeriod(4000);  //4ms
     startOutputSignal_on_PT4();
     
     for(j=0;j<=period;j++)
      {
        changeDuty(j);
        for(i=0;i<0x3FF;i++) asm nop;        // SW delay
      }
     for(i=0;i<0x1FFFFF;i++) asm nop;        // SW delay
    }           
}
//******************************************************************************
// void changePeriod(ULONG period)
//******************************************************************************
// timer frequency = BUSCLK/(TC7+1)/prescaler=BUSCLK/(TC7+1)/16
// 50% duty cycle; = (TC7-1)/2

void changePeriod(ULONG per_us) //[us]; (1.28us < period < 41942.4us) for 25MHz busclk and tim prsclr=16 (see TSCR2 setup)
{                               // max err in the setup is (TC7min+1)*16/busclk=(0+1)*16/25000000=640ns
ULONG per;
per  = per_us*BUSCLK/1000/16-1;
ECT_TC7  = (UWORD) per;
period = (UWORD) per;
}
//******************************************************************************
// void changeDuty(UWORD duty)
//******************************************************************************
void changeDuty(UWORD duty) //[us]; (1.28us < period < 41942.4us) for 25MHz busclk and tim prsclr=16
{               // max error in the setup is (TC7min+1)*16/busclk=(0+1)*16/25000000=640ns
if(duty>period) duty=period;
ECT_TC4  = duty;
}
//******************************************************************************
// void permanent_1_on_PT4(void)
//******************************************************************************
void permanent_1_on_PT4(void)
{
  ECT_TCTL1 |= ECT_TCTL1_OM4_MASK | ECT_TCTL1_OL4_MASK; // channel 4 - PT4 - set output on compare, channels 0,2,3 disconnected from output pin logic
  ECT_OC7D  |= ECT_OC7D_OC7D4_MASK;                 // set PT4 on PT7 compare
}
//******************************************************************************
// void startOutputSignal(void)
//******************************************************************************
void startOutputSignal_on_PT4(void)
{
// see description of stopOutputSignal
  ECT_TCTL1 &= (~(ECT_TCTL1_OM4_MASK | ECT_TCTL1_OL4_MASK)); // clear bits of channel PT4
  ECT_TCTL1 |= ECT_TCTL1_OM4_MASK;                       // channel 4 - PT4 - clear output on compare, channels 0,2,3 disconnected from output pin logic
  ECT_OC7D |= ECT_OC7D_OC7D4_MASK;                       // set PT4 on PT7 compare
}
//******************************************************************************
// void stopOutputSignal(void)
//******************************************************************************
void stopOutputSignal_on_PT4(void)        // log 0 on PT4
{ // do not use OMn,OLn bit combination "Disconnected from output pin logic"
  // because in the case of PT7 is used as a period generator then this option does not
  // work. - Not documented erratum - I discovered it 3 weeks ago. The bug is in solution.
  
  // The solution can be done by correct signal setup. Because, on the TC7 compare bit OC7D bit n says
  // "set corresponding channel n to 1 on TC7 compare" and the channel n compare action is clear on compare
  // then it is enough to change OC7D bit n to 0 => clear corresponding bit of channel n on TC7 compare.
  ECT_TCTL1 &= (~(ECT_TCTL1_OM4_MASK | ECT_TCTL1_OL4_MASK)); // channel 4 - PT4 - clear output on compare, channels 0,2,3 disconnected from output pin logic
  ECT_OC7D  &= (~ECT_OC7D_OC7D4_MASK);                   // clear PT4 on PT7 compare
}
//******************************************************************************
// static void TimerSetup(void)
//******************************************************************************
void TimerSetup(void)
{
//--- channel 0-7 setup -------------------
ECT_TCTL1 = 0x01;                          // channels 7-5 disconnected from output pin logic
ECT_TIOS  = 0x90;                          // channel 7,4 - PT4 - output compare
ECT_OC7M  = ECT_OC7M_OC7M4_MASK;           // channel 4 - PT4 - is an output port for channel 7 compare
//-----------------------------------------
changePeriod(10000);                       // [us]; (1.28us < period < 41942.4us) for 25MHz busclk and tim prsclr=16
changeDuty(period/2);                      // 50% duty cycle
stopOutputSignal_on_PT4();                 // channel 4 - PT4 - set PT4 on PT7 compare =>left aligned PWM
ECT_TSCR2 = 0x0C;                          // prescaler =16,reset tim by a output compare of channel 7
                                            // ovf int disable
//-----------------------------------------
ECT_TSCR1 = 0xF0;                          // enable timer,stop in wait,stop in freeze, fast flag clear
}
//******************************************************************************
// static void PLL_Init(UBYTE syn, UBYTE refdv)
//******************************************************************************
static void PLL_Init(UBYTE synr, UBYTE refdv, UBYTE postdiv)
{
  PLLCTL_PLLON  = 0;                        // Disable the Phase Lock Loop   
  CLKSEL_PLLSEL = 0;                        // Select clock source from OSCCLK
  CLKSEL_PLLWAI = 1;                        // PLL stops in wait mode     
  SYNR          = synr;   
  REFDV         = refdv;  
  POSTDIV       = postdiv;
  PLLCTL_PLLON  = 1;                        // Enable the Phase Lock Loop   
  while(!CRGFLG_LOCK);                      // Wait till the PLL VCO is within tolerance
  CLKSEL_PLLSEL = 1;                        // Select clock source from PLLCLK
}
//******************************************************************************
// Services performed by FREESCALE in this matter are performed AS IS and without any warranty. CUSTOMER retains
// the final decision relative to the total design and functionality of the end product. FREESCALE neither
// guarantees nor will be held liable by CUSTOMER for the success of this project.
// FREESCALE DISCLAIMS ALL WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY INCLUDING, BUT NOT LIMITED TO, IMPLIED
// WARRANTY OF MERCHANTABILITY OR  FITNESS FOR A PARTICULAR PURPOSE ON ANY HARDWARE, SOFTWARE ORE ADVISE SUPPLIED
// TO THE PROJECT BY FREESCALE, AND OR NAY PRODUCT RESULTING FROM FREESCALE SERVICES . IN NO EVENT SHALL FREESCALE
// BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT.
//
// CUSTOMER agrees to hold FREESCALE harmless against any and all claims demands or actions by anyone on account of
// any damage, or injury, whether commercial, contractual, or tortuous, rising directly or indirectly as a result of
// the advise or assistance supplied CUSTOMER in connection with product, services or goods supplied under this Agreement.
//******************************************************************************

出0入0汤圆

 楼主| 发表于 2012-12-11 17:21:04 | 显示全部楼层
dingyigr顶一个

出0入0汤圆

 楼主| 发表于 2012-12-11 21:29:23 | 显示全部楼层
#include <stc89c5x.h>//STC89C52

//串行驱动1602,powered by 595
#define LCD1602_BACKLIGHT        P1_3//背光
#define LCD1602_SDA                        P1_0//数据输入
#define LCD1602_SCK                        P1_1//移位时钟,SHCP,11pin
#define LCD1602_SCL                        P1_2//锁存时钟,STCP,12pin

/*
* 硬件连接:
* 74HC595 Q7 - 1602 RS
* GND - 1602 RW(595没有输入功能,所以判定忙只能*延时,另外就是MCU的速度比较的慢。所以也可以直接去掉延时。但是在STC12系列上的表现,相当的不错
* 在传统51上面。PWM占空比低于50%将会出现扫描线。12系列的,很高兴的告诉大家。T0X12开了以后。不会有扫描线出现。但是如果一定要在传统51上使用的话,请把10级调光改成4级。谢谢合作!
* 74HC595 Q6 - 1602 EN
* 74HC595 Q5~Q2 - 1602 D5~D7(这一次硬件设计不合理,才只能搞软件修正了。不过好处就是直接就可以洞洞板上对着联,减少了烧坏595的概率。坏处就是CPU时间消耗的多了点。但是可以取消延时函数啦~
* 1602 D1~D4 直接悬空
* LCD_BACKLIGHT加一级PNP三极管射随器加到液晶的A上,如果无需调光可以去掉这一部分电路和代码
* 至于595的连接,只要不弄反SCL和SCK,就没有问题啦~
*/

__sbit  __at  0xE0 A_0;//方便位操作,硬件设置真的是败笔 - -
__sbit  __at  0xE1 A_1;
__sbit  __at  0xE2 A_2;
__sbit  __at  0xE3 A_3;
__sbit  __at  0xE4 A_4;
__sbit  __at  0xE5 A_5;
__sbit  __at  0xE6 A_6;
__sbit  __at  0xE7 A_7;
__sbit  __at  0xF1 B_1;
__sbit  __at  0xF2 B_2;
__sbit  __at  0xF3 B_3;
__sbit  __at  0xF4 B_4;
__sbit  __at  0xF5 B_5;
__sbit  __at  0xF6 B_6;
__sbit  __at  0xF7 B_7;

unsigned char PWM_Cycle=0;//PWM占空比
unsigned char PWM_T=0;//PWM当前所处周期
unsigned char OutBuf=0xff;//输出缓冲
#define        LCD_OFF         lcd_wcmd(0x08)
#define        LCD_CUR         lcd_wcmd(0x0E)
#define        LCD_FCUR       lcd_wcmd(0x0F)
void delay(unsigned int n)
{
unsigned int x,y;
for(x=n;x>0;x--)
for(y=100;y>0;y--);
}

void Send595()
{
        unsigned char i,j;
        j=0x80;
        LCD1602_SCK=0;
        for(i=0;i<8;i++)
        {
                LCD1602_SDA=OutBuf & j;
                j=j>>1;
                LCD1602_SCK=1;
                LCD1602_SCK=0;
        }
        LCD1602_SDA=1;
        LCD1602_SCL=0;
        LCD1602_SCL=1;
}
void lcd_en()
{
        //OutBuf=OutBuf|0x40;//E=1
        B=OutBuf;
        B_6=1;
        OutBuf=B;
        Send595();//输出数据
        B=OutBuf;
        B_6=0;
        OutBuf=B;//E=0
        Send595();
}

/**********************************************************/
void lcd_wcmd(unsigned char i)
{
//写命令
        B=OutBuf;
        B_7=0;//RS=0,RW=0;
        OutBuf=B;
        Send595();
//--------------
        B=OutBuf;
        ACC=i;
        B_2=A_7;//D7=D7
        B_3=A_6;//D6=D6
        B_4=A_5;//D5=D5
        B_5=A_4;//D4=D4
        OutBuf=B;
        Send595();
        lcd_en();
//================
        ACC=i;
        B=OutBuf;
        B_2=A_3;//D7=D3
        B_3=A_2;//D6=D2
        B_4=A_1;//D5=D1
        B_5=A_0;//D4=D0
        OutBuf=B;        
        Send595();
        lcd_en();
}
void lcd_wdat(unsigned char i)
{
//写数据
        B=OutBuf;
        B_7=1;//RS=0,RW=0;
        OutBuf=B;
        Send595();
//--------------
        B=OutBuf;
        ACC=i;
        B_2=A_7;//D7=D7
        B_3=A_6;//D6=D6
        B_4=A_5;//D5=D5
        B_5=A_4;//D4=D4
        OutBuf=B;
        Send595();
        lcd_en();
//================
        ACC=i;
        B=OutBuf;
        B_2=A_3;//D7=D3
        B_3=A_2;//D6=D2
        B_4=A_1;//D5=D1
        B_5=A_0;//D4=D0
        OutBuf=B;        
        Send595();
        lcd_en();
}

void lcd_putchar(unsigned char addr,unsigned char ch)
{//写一个字
        lcd_wcmd(0x80+addr);
        lcd_wdat(ch);
}

void lcd_display(unsigned char *l1,unsigned char *l2)
{//写一屏幕
        unsigned char i=0;
        lcd_wcmd(0x80); //显示地址设为80H(即00H,)上排第一位
        for(i=0;i<16;i++)
        {
                lcd_wdat(l1);
        }
        lcd_wcmd(0x80+0x40); //重新设定显示地址为0xc0,即下排第1位
        for(i=0;i<16;i++)
        {
                lcd_wdat(l2);
        }
}

void lcd_cls()
{
        lcd_wcmd(0x01); //清屏延时函数可以省略
}
//米有读函数,但是功能可以由上面的函数扩展哦~
void lcd_init()
{
    OutBuf=0xff;
    Send595();//复位VIO,这段代码必须加。否则MCU忽然RESET会导致液晶乱码
    lcd_wcmd(0x30);//复位1602,这段代码必须加,同上
    lcd_en();//唤醒
        lcd_wcmd(0x20);
        lcd_en();//唤醒
        lcd_wcmd(0x28); //四位,5x7
        lcd_wcmd(0x0c); //开启显示屏,关光标,光标不闪烁
        lcd_wcmd(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
        lcd_wcmd(0x01); //清屏        
        //调试的时候被设计失误的对比度电位器坑死了:就是两排小方块死都不显示
        //查了半天都不知道
        //最后捅了下电位器就正常了……
}
void lcd_print(unsigned char *str)
{
    unsigned char addr=0x80,len=0;
    lcd_wcmd(addr); //显示地址设为80H(即00H,)上排第一位
    while(*str!='\0')
    {//等待末尾
        if(len >= 16)
        {
            lcd_wcmd(0x80+0x40);//下排第一位,换行
            len=0;
        }
        if(*str=='\n')
        {
            lcd_wcmd(0x80+0x40);//下排第一位,换行
        }
        else
        {
            lcd_wdat(*str);   
        }
        str++;
        len++;
    }
}//写字符串函数
void PWM() __interrupt 1 __using 1
{
        ET0=0;
        TF0=0;//CLR
        TR0=0;
        EA=0;
        TH0=0xFC;TL0=0x00;//十级调光,频率400Hz
        if(PWM_T>10) {PWM_T=0;}
        if(PWM_Cycle>PWM_T){ LCD1602_BACKLIGHT=0;}
        if(PWM_Cycle<PWM_T)  {LCD1602_BACKLIGHT=1;}
        PWM_T++;
        TR0=1;
        ET0=1;
        EA=1;
}

void main()
{//主函数

        TMOD = 0x01 ;
        TH0=0xFC;TL0=0x00;
        TR0=1;ET0=1;
        EA=1;//开中断
        //-----------------
        lcd_init();
        PWM_Cycle=10;//背光100%
        //液晶初始化---------
        while(1)
        {
                lcd_display("  Hello world!  ","Serial mode 1602");
                delay(2000);
                lcd_display("Drive by 74HC595","Design by rgwan ");
                delay(2000);
                lcd_display("Website address:"," www.rwzy.co.cc ");
                delay(2000);
                lcd_display("Backlight ctl by","  T0 PWM 400Hz  ");
                delay(2000);
        }
}

回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 06:34

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表