//RSTDISBL(1):禁用RST---->1(禁用) SPIEN(0):使能SPI------>0(使能) EESAVE(1):编程保留EEPROM->1(擦除) BOOTSZ1(0):boot区空间->0(默认)
//WDTON(1):WDT开---->1(关) CKOPT(1):振荡器形式->1(晶体) BOOTSZ0(0):boot区空间->0(默认) BOOTRST(1):复位地址->1(地址0000)
//BODLEVEL(1):BOD电平->0(4V) BODEN(1):使能BOD->0(使能) SUT10(10):启动时间->00(BOD使能推荐)
//CKSEL3210(0001):时钟源->0100 (片内8M)
//可能电机转动时造成电源电压拨动,单片机反复复位,暂且将BODLEVEL和BODEN功能取消。
#include <iom8v.h>
#include <macros.h>
#define XTAL 8
#define MCP_ON() PORTD&=0x7F;
#define MCP_OFF() PORTD|=0x80;
#define RSTMCP() PORTD&=0xBF; delay(50); PORTD|=0x40;delay(50);
#define OUT_OFF() PORTD|=0x20;
#define OUT_ON() PORTD&=0xDF;
//0x12左手,0x22右手
#define MYID 0x12
#define MYMASK 0xff
#define MASTERID 0x02
unsigned char receive_master[8];
unsigned char pos1,pos2,speed1,speed2,vv1,vv2;
unsigned char flag1,flag2; //位置更新标志
unsigned int pwm1,pwm2;
unsigned int tt1,tt2; //比较变量
void send_data(unsigned char j);
//------------------------------------------------------------------------毫秒延时
void delay(unsigned int ms)
{
unsigned int i;
unsigned int j;
for(i=0;i<ms;i++)
{ for(j=0;j<(XTAL*143-2);j++);
}
}
//------------------------------------------------------------------------约百微秒延时
void delay100(unsigned int ms)
{
unsigned int i;
unsigned int j;
for(i=0;i<ms;i++)
{ for(j=0;j<(XTAL*10);j++);
}
}
//-----------------------------------------------------------------------端口初始化
void port_init(void)
{
PORTB = 0x2E;// 7 6 5 4 | 3 2 1 0
DDRB = 0x2E;// SCK ISO OSI PWMB PWMA MOSI必须设置成输出
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0xE0;// 7 6 5 4 | 3 2 1 0
DDRD = 0xE0;// MCP RSTMCP OUT0
}
//----------------------------------------------------------------------dog初始化
void wdt_init(void)
{
WDR();
WDTCR=0x1f;//此处与atmega16不一致
WDTCR=0x0f;//使能,分频比=1:7 =》 2.1s
}
//---------------------------------------------------------------------timer1初始化
void timer1_init(void)
{
TCCR1B = 0x00; //stop
OCR1A = 0x300; //default
OCR1B = 0x300;
ICR1 = 0x4E1F; //top =20,000 uS
TCCR1A = 0xA2; //匹配时置低电平,快速PWM,TOP=ICR1.
TCCR1B = 0x1a; //开始,8M晶振-8分频,单位时间1uS
}
//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■mcp部分
void spi_init(void)
{
SPCR=0x50;//spi使能,主机模式,时钟4分频
}
//---------------------------------------------------------------------spi读写
unsigned char spi_run(unsigned char data)
{ SPDR = data;
while(!(SPSR&0x80));//SPSR.8(SPIF)=1,发送完成
return SPDR;
}
//-----------------------------------------------------------------------mcp读
unsigned char read_mcp(unsigned char address)
{ unsigned char data;
MCP_ON();
spi_run(0x03); //mcp读指令
spi_run(address); //写地址
data=spi_run(0xFF);//空时钟返回数据
MCP_OFF();
return data;
}
//-----------------------------------------------------------------------mcp写
void write_mcp(unsigned char address,unsigned char data)
{ MCP_ON();
spi_run(0x02); //mcp写指令
spi_run(address); //写地址
spi_run(data); //写数据
MCP_OFF();
}
//--------------------------------------------------------------------mcp初始化
void mcp_init(unsigned int id,unsigned int mask)
{ RSTMCP();
MCP_ON();
spi_run(0xC0);//复位
MCP_OFF();
delay(10);
write_mcp(0x2A,0x00);
write_mcp(0x29,0x90);
write_mcp(0x28,0x02);//设置波特率
write_mcp(0x00,(id>>3)&0x00ff);
write_mcp(0x01,(id<<5)&0x00e0);
write_mcp(0x20,(mask>>3)&0x00ff);
write_mcp(0x21,(mask<<5)&0x00e0);
write_mcp(0x60,0x00);
write_mcp(0x0f,0x08);//正常模式
MCP_OFF();
delay(10);
write_mcp(0x2B,0x01);//接收中断使能
}
//-----------------------------------------------------------------------can发送
void send_can( unsigned int ID,unsigned char data[8],unsigned mm )
{
write_mcp(0x31,(ID>>3)&0xff);//目标ID的高位
write_mcp(0x32,(ID<<5)&0xe0);//目标ID的地位
write_mcp(0x35,mm); //TXB0DLC: 1数据帧,8字节
write_mcp(0x36,data[0]); //TXB0D0: 发送的数据。
write_mcp(0x37,data[1]);
write_mcp(0x38,data[2]);
write_mcp(0x39,data[3]);
write_mcp(0x3a,data[4]);
write_mcp(0x3b,data[5]);
write_mcp(0x3c,data[6]);
write_mcp(0x3d,data[7]);
write_mcp(0x30,0x0f); //TXB0CTRL:开始发送
}
//-----------------------------------------------------------------------can接收
//---------------------------------------------------------------------int初始化
void int_init(void)
{
MCUCR=0x0a; //CPU正常模式int0,int1下降沿中断
GICR=0x40; //外部中断int0中断有效
}
//----------------------------------------------------------------------int0中断
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
unsigned char i;
for(i=0;i<8;i++) receive_master[i]=read_mcp(0x66+i);
if(receive_master[0]==0xaa)
{
pos1=receive_master[1]; //1轴位置
speed1=receive_master[2]; //1轴速度
if(pos1>180)pos1=180; //pwm:20mS占空比(范围500uS-2500uS);
pwm1=500+pos1*100/9; //pos:接收的角度(单位0°-180°)
if(speed1>0x64)speed1=0x64; //pwm1=500uS+(pos*2000uS/180°)
speed1=0x64-speed1;
flag1=1;
}
write_mcp(0x2c,0x00);//中断复位
}
//--------------------------------------------------------------------------主函数
void main(void)
{
CLI(); //disable interrupt
timer1_init();
port_init();
spi_init();
mcp_init(MYID,MYMASK);
int_init();
wdt_init();
SEI(); //enable interrupt
OUT_ON();delay(100);OUT_OFF();
OCR1A = 500; //default
pwm1 = 500; //初始位置0.5ms
tt1 = 500;
vv1=3;
while(1)
{
WDR();
while(vv1==0)
{
if((flag1==1)||(pwm1!=tt1))//解决恰巧在flag=0之前产生中断
{
if(pwm1>tt1) tt1++; //步进0.1°
else if(pwm1<tt1) tt1--;
OCR1A=tt1; OUT_ON();
}
if(pwm1==tt1) {flag1=0; OUT_OFF();}
vv1=speed1+1;
}
vv1--;
delay100(1);
}
}
pwm.zip_atmega8 PWM_visual c
版权申诉
166 浏览量
2022-09-14
19:31:57
上传
评论
收藏 3KB ZIP 举报
![avatar](https://profile-avatar.csdnimg.cn/d600a32f29294db1a3be82ec9708491a_weixin_42651887.jpg!1)
weixin_42651887
- 粉丝: 81
- 资源: 1万+