📄 main.c
字号:
//ICC-AVR application builder : 2007-5-29
// Target : M8
// Crystal: 11.059Mhz
/** MCU1的程序
* 功能:
* 1. 控制直流电机正、反转,停止
* 2. 用快速PWM方式(模式14)调节电机转速
* 3. 用串口接收MCU2传来的PWM占空比(脉宽)
*/
#include <iom8v.h>
#include <macros.h>
#define FORWARD 0x00
#define BACKWARD 0x01
#define STOP 0x02
/*
PB0------in1
PB1------in2(OC1A)
PB2------in3(OC1B)
PB3------in4
*/
//初始时向前转
unsigned char dir_flag; // dir_flag 电机方向标记
unsigned char data=0, // 接收字符临时存入data
Rec_data[10]={0}; // 接收数组
unsigned char uart_rece_flag=0; // 接收完成标志
void port_init(void)
{
PORTB = 0x0F;//0000 1111
DDRB = 0x0F;//0000 1111
PORTC = 0x31;//0011 0001
DDRC = 0x31;//0011 0001
PORTD = 0xf0;//1111 0000
DDRD = 0xc3;//1100 0011
}
//TIMER1 initialize - prescale:1
// WGM: 14) PWM fast, TOP=ICRn
// desired value: 20KHz
// actual value: 20.034KHz (0.2%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x00; //setup
TCNT1L = 0x00;
OCR1AH = 0x02;
OCR1AL = 0x27;
OCR1BH = 0x02;
OCR1BL = 0x27;
ICR1H = 0x02; // 20kHz
ICR1L = 0x27;
TCCR1A = 0x02; // OCR1A未连接,做普通端口操作
TCCR1B = 0x19; //start Timer
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
PORTB&=~(1<<1);// 输出比较匹配时,PB0,PB1全部为低,使得运动停止
PORTB&=~(1<<0);
}
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
// 定时器1溢出中断处理
{
if(dir_flag==FORWARD)
{//如果要求电机正转
PORTB&=~(1<<0); // pb0=0=in1
PORTB|=(1<<1); // pb1=1=in2
}
else if(dir_flag==BACKWARD)
{//如果要求电机反转
PORTB&=~(1<<1); // pb1=0
PORTB|=(1<<0); // pb0=1
}
else//如果要求电机停止
{
PORTB&=~(1<<1); // pb0=0
PORTB&=~(1<<0); // pb1=0
}
}
//UART0 initialize
// desired baud rate: 9600
// actual: baud rate:9600 (0.0%)
// char size: 8 bit
// parity: Disabled
void uart0_init(void)
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x06;
UBRRL = 0x47; //set baud rate lo
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x90;
}
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr(void)
// 串口接收中断处理
// 记录接收到的字符,根据协议将接收到的数据存入数组Rec_data[]
{
//uart has received a character in UDR
static unsigned char rece_num=0; // 接收字节数计数
data=UDR; // 接收字符临时存入data
if((data==0xAA)&&(rece_num==0))//判断第0字节,0XAA起始位判断
{
Rec_data[rece_num]=data; // 根据协议,记录通信字节
rece_num++; // 接收字符数计数加1
}
else if(rece_num>0)//第1字节到第7字节寄存到接收数据中
{
Rec_data[rece_num]=data;
rece_num++;
if(rece_num==8)//接收完毕,标志位置1
{
rece_num=0; //准备接收下一帧字节
uart_rece_flag=1;
}
}
}
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
// 外部中断0处理,电机停止
{
//external interupt on INT0
dir_flag=STOP;
PORTB&=~(1<<0); // pb0=0
PORTB&=~(1<<1); // pb1=0
}
//call this routine to initialize all peripheralsz
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer1_init();
uart0_init();
MCUCR = 0x0A;
GICR = 0x40;
TIMSK = 0x14; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//
void main(void)
{
unsigned char i=0;
init_devices();
dir_flag=STOP; // 初始化,电机停转
while(1)
{
if(uart_rece_flag==1) // 接收完成位置位后,改变PWM占空比
{
i++;
if(i<=25) // 每接收25次改变一次PC的led7显示状态
{
PORTD&=~(1<<7);//接收到数后led7闪烁
}
else if(i<=50)
{
PORTD|=1<<7;//接收到数后led7闪烁
}
else
{
i=0;
}
uart_rece_flag=0; // 串口接收完成位清0
if(Rec_data[1]==0) // Rec_data[1]=pwmtemph
{ // 占空比快为0时,停止电机
if(Rec_data[2]<=0x05) // Rec_data[2]=pwmtempl
{
dir_flag=STOP;
}
}
else if(!(Rec_data[1]&(1<<7))) //pwmtemph最高位为电机方向位
{
dir_flag=FORWARD;//如果最高位为0,则为正向
}
else
{
dir_flag=BACKWARD;
Rec_data[1]-=1<<7; // pwmtemph最高位清0,电机反向
}
// 改变输出比较寄存器OCR1A,改变占空比
OCR1AH=Rec_data[1];
OCR1AL=Rec_data[2];
} // end if
} // end while
} // end main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -