程序如下:(用串口调试助手发送给M16,不知道为什么在示波器上显示不了波形?)我是想用定时器的比较匹配中断和溢出中断来模拟输出占空比可变的PWM,希望大家帮忙看下交流,共同进步,如果有更好的方法也可提出来,除了自带的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[5];
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[0]=UDR;
if(data[0]==0x55)
{
do
{
while(!(UCSRA&(1<<RXC)));
i++;
data=UDR;
if(i==4)
break;
}while(1);
if((data[3]==0xFF&&data[4]==0xFF))
datadisposal();
}
SREG|=BIT(7);
}
void datadisposal(void)
{
shebei=data[1];
caozuo=data[2];
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);
}
else if(class_dianji==2)
{
num_dianji=shibie_dianjihao(shebei);
fun1_dianji(num_dianji);
}
}
void main(void)
{
init_devices();
do{}while(1);
}
[local]1[/local] |