aleko 发表于 2009-11-15 03:14:06

关于用串口接收来控制直流电机(模拟PWM)?

程序如下:(用串口调试助手发送给M16,不知道为什么在示波器上显示不了波形?)我是想用定时器的比较匹配中断和溢出中断来模拟输出占空比可变的PWM,希望大家帮忙看下交流,共同进步,谢谢!

#include<iom16v.h>
#include<macros.h>
#define uint unsigned int
#define uchar unsigned char

uchar shebei;
uchar caozuo;
uchar class_dianji;
uchar num_dianji;
uchar data;

void port_init(void)
{
        DDRB|=BIT(PB3);//一号直流电机PWM输出
        DDRD|=BIT(PD4);//二号直流电机PWM输出
        DDRD|=BIT(PD7);//三号直流电机PWM输出
        DDRB|=0X03;//一号直流电机使能,方向
        DDRC|=0X18;//二号直流电机使能,方向
        DDRC|=0X60;//三号直流电机使能,方向
        PORTA&=0X00;
        PORTB&=0X00;
        PORTC&=0X00;
        PORTD&=0X00;
}

void timer0_init(void)
{
        TCCR0 = 0x00; //stop
        TCNT0 = 0x83; //set count
        OCR0 = 0xB4; //set compare
}

void timer1_init(void)
{
        TCCR1A=0x00;
        TCCR1B=0x00;//stop
        TCNT1H=0x00;
        TCNT1L=0x83;//set count
        OCR1AH=0x00;
        OCR1AL=0xB4; //set compare
}

void timer2_init(void)
{
        TCCR2 = 0x00; //stop
        TCNT2 = 0x83; //set count
        OCR2 = 0xB4; //set compare
}

void uart_init(void)//中断初始化
{
        UCSRB=0x00;//禁止接收
        UCSRC=0x86;//8位数据位
        UBRRH=0x00;
        UBRRL=0x33;//波特率9600
        UCSRB=0x90;
        //DDRD&=~BIT(0);
        //SREG|=BIT(7);
}

void init_devices(void)
{
        //stop errant interrupts until set up
        CLI(); //disable all interrupts
        port_init();
        uart_init();
        timer0_init();
        timer1_init();
        timer2_init();
        MCUCR=0x00;
        GICR=0x00;
        TIMSK=0xD7; //timer interrupt sources 允许定时器0,1,2零匹配和溢出中断
        SEI(); //re-enable interrupts
        //all peripherals are now initialized
}

#pragma interrupt_handler timer0_pipei:20
void timer0_pipei(void)
{
        //compare occured TCNT0=OCR0
        CLI();
        PORTB|=BIT(PB3);
        SEI();
}

#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
        CLI();
        TCNT0 = 0x83; //reload counter value
        PORTB&=~BIT(PB3);
        SEI();
}

#pragma interrupt_handler timer1_pipei:7
void timer1_pipei(void)
{
        CLI();
        PORTD|=BIT(PD4);
        SEI();
}

#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
{
        CLI();
        TCNT1H=0x00;
        TCNT1L=0x83;
        PORTD&=~BIT(PD4);
        SEI();
}

#pragma interrupt_handler timer2_pipei:4
void timer2_pipei(void)
{
        CLI();
        PORTD|=BIT(PD7);
        SEI();
}

#pragma interrupt_handler timer2_ovf_isr:5
void timer2_ovf_isr(void)
{
        CLI();
        TCNT2 = 0x83; //reload counter value
        PORTB&=~BIT(PD7);
        SEI();
}

#pragma interrupt_handler uart_rxc:12
void uart_rxc(void)
{
        uchar i;
        SREG&=~BIT(7);
        data=UDR;
        if(data==0x55)
        {
               do
                {
                          while(!(UCSRA&(1<<RXC)));
                        i++;
                        data=UDR;
                        if(i==4)
                        break;
                }while(1);
                if((data==0xFF&&data==0xFF))
                datadisposal();
        }
        SREG|=BIT(7);
}

void datadisposal(void)
{
        shebei=data;
        caozuo=data;
        act();
}

uchar shibie_dianji(uchar a)//识别电机
{
       uchar dianji;
       a&=0X18;
       switch(a)
       {                                                                                                       
               case 0X08 :
                dianji=1;break;       
                case 0X10 :
                dianji=2;break;               
       }
       return dianji;                                                                                                                         
}

uchar shibie_dianjihao(uchar b)//识别电机号
{
        uchar dianjihao;
        b&=0X07;
        switch(b)
        {
                case 0X00 :
                dianjihao=1;break;
                case 0X01 :
                dianjihao=2;break;
                case 0X02 :
                dianjihao=3;break;
                case 0X03 :
                dianjihao=4;break;
                case 0X04 :
                dianjihao=5;break;
                case 0X05 :
                dianjihao=6;break;
        }
        return dianjihao;
       
}
       
void fun1_dianji(uchar d)//电机驱动函数
{
        switch (d)
        {
                case 1 :
                {
                        if((caozuo&0X40)==0X00)
                        {
                                PORTB|=BIT(PB1);//brake
                                        if((d&0X20)==0X20)
                                        {
                                                PORTB|=BIT(PB0);//dir正转
                                        }
                                        else
                                        {
                                                PORTB&=~BIT(PB0);//dir反转
                                        }
                                TCCR0=0x02;
                                if((caozuo&0x01)==0)
                                OCR0=0xB4;
                                else
                                OCR0=0xE1;
                        }
                }
                case 2 :
                {
                        if((caozuo&0X40)==0X00)
                        {
                                PORTC|=BIT(PC4);//brake
                                        if((caozuo&0X20)==0X20)
                                        {
                                                PORTC|=BIT(PC3);//dir正转
                                        }
                                        else
                                        {
                                                PORTC&=~BIT(PC3);//dir反转
                                        }
                                TCCR1B=0x02;
                                if((caozuo&0x01)==0)
                                {OCR1AH=0x00;
                               OCR1AL=0xB4;}
                                else
                                {OCR1AH=0x00;
                               OCR1AL=0xE1;}
                        }
                }
                case 3 :
                {
                        if((caozuo&0X40)==0X00)
                        {
                                PORTC|=BIT(PC6);//brake
                                        if((caozuo&0X20)==0X20)
                                        {
                                                PORTC|=BIT(PC5);//dir正转
                                        }
                                        else
                                        {
                                                PORTC&=~BIT(PC5);//dir反转
                                        }
                                TCCR2=0x02;
                                if((caozuo&0x01)==0)
                                OCR2=0xB4;
                                else
                                OCR2=0xE1;
                        }
                       
                }
        }
}

void act(void)
{
                class_dianji=shibie_dianji(shebei);
               if(class_dianji==1)
               {
                      num_dianji=shibie_dianjihao(shebei);
                        fun1_dianji(num_dianji);
               }
               elseif(class_dianji==2)
               {
                      num_dianji=shibie_dianjihao(shebei);
                        fun1_dianji(num_dianji);
               }
}

void main(void)
{
        init_devices();
        do{}while(1);
}


点击此处下载 ourdev_503295.txt(文件大小:5K) (原文件名:PWM控制直流电机.txt)

aleko 发表于 2009-11-15 03:20:11

发送数据的协议是起始字节是0xFF,中间两个字节是有效数据,终止字节是0xFF,0xFF。第一个有效数据的第三位是选择电机号,第4位和第5位是识别电机,看是步进电机还是直流电机(步进电机的没上传),第二个有效数据时操作,我是搭的H桥双极性可逆的PWM驱动电路,这个字节的第三位分别代表电机启动,电机方向和PWM调速(只设定了两档)

aleko 发表于 2009-11-15 21:25:12

怎么没人回啊?大家给提点意见啊!
页: [1]
查看完整版本: 关于用串口接收来控制直流电机(模拟PWM)?