📄 midialarm.c
字号:
TWCR = ()
break;
case 0x70 : twi_flag = 0;
break;
case 0x78 : twi_flag = 0;
break;
default : twi_init();
TWCR = (1<<TWIE) | (1<<TWEN) ;
return 0;
}
TWCR = (1<<TWINT) | (1<<TWEA); //ACK
twi_count = 0; //初始化计数器
while(1)
{
TWCR |= (1<<TWINT); //清零中断标志位
j = 0;
while(!(TWCR & (1<<TWINT)) && j <= 10000){j++;}
if(j>10000)
{
twi_init();
TWCR = (1<<TWIE) | (1<<TWEN) ;
return 0;
}
switch(TWSR & 0xF8)
{
case 0x80 : twi_flag = 0;
break;
case 0x88 : twi_flag = 1;
break;
case 0x90 : twi_flag = 0;
break;
case 0x98 : twi_flag = 1;
break;
case 0xA0 : twi_flag = 0;
TWCR |= (1<<TWINT);
I2cRnum = twi_count; //记录收到的字节数
return twi_count;
default : twi_init();
TWCR = (1<<TWIE) | (1<<TWEN) ;
return 0;
}
if(twi_flag)
{
twi_init();
TWCR = (1<<TWIE) | (1<<TWEN) ;
return 0;
}
I2cRbuf[twi_count] = TWDR; //将接收到的数据存入i2c接收缓存
twi_count++;
if(twi_count>8)
break;
}
return twi_count;
}*/
/***********************************************
总线上启动开始条件程序:twi_start() 返回值 1:发送成功 0:发送失败
***********************************************/
uchar twi_start()
{
uchar twi_flag,n;
uint j;
n = 0;
twi_flag = 1; // 1:defeat 0:success
while(twi_flag)
{
n++;
if(n>5)
{
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA); //发送起始电平
j=0;
while(!(TWCR&(1<<TWINT)) && j<=10000){j++;}
if(j>10000)
{
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
switch(TWSR & 0xF8)
{
case 0x08 : twi_flag = 0;
break; //发送起始位成功
case 0x10 : twi_flag = 0;
break;
case 0x38 : twi_flag = 1;
break;
default : twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
if(!twi_flag)
return 1;
}
return 0;
}
/***********************************************
总线上启动停止条件程序:twi_stop()
***********************************************/
void twi_stop()
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
DelayMs(10);
}
/*****************************************************
AVR通过I2C总线向AT24C512写数据(字节写): twi_writebyte
*****************************************************/
uchar twi_writebyte(uchar wrdata)
{
uchar twi_flag,n;
uint j;
twi_flag = 1;
n = 0;
while(twi_flag)
{
n++;
if(n>100)
{
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
TWDR = wrdata;
TWCR = (1<<TWINT) | (1<<TWEN);
j = 0;
while(!(TWCR&(1<<TWINT)) && j<=10000){j++;}
if(j>10000)
{
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
switch(TWSR & 0xF8)
{
case 0x18 : twi_flag = 0; //发送从设备写,收到应答
break;
case 0x20 : twi_flag = 1;
break;
case 0x28 : twi_flag = 0; //发送数据,收到应答
break;
case 0x30 : twi_flag = 1;
break;
case 0x38 : twi_flag = 1;
break;
case 0x40 : twi_flag = 0; //发送从设备读,收到应答
break;
case 0x48 : twi_flag = 1;
break;
default : //usart_txc(TWSR&0xF8);
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
if(!twi_flag)
return 1;
}
return 0;
}
/***********************************************
AVR通过I2C从AT24C512读一个字节程序: twi_readbyte
***********************************************/
uchar twi_readbyte(uchar redata, uchar ack) //true为ack false为nack
{
uchar temp,j;
temp = 0;
temp = (1<<TWINT) | (1<<TWEN);
if(ack)
temp |= (1<<TWEA);
TWCR = temp;
j=0;
while(!(TWCR&(1<<TWINT)) && j<=10000){j++;}
if(j>10000)
{
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
redata = TWDR;
usart_txc(redata);
switch(TWSR & 0xF8)
{
case 0x38 : return 0;
case 0x50 : return 1;
case 0x58 : return 1;
default : //usart_txc(TWSR&0xF8);
twi_init();
TWCR = (1<<TWEA) | (1<<TWEN);
return 0;
}
}
/*************************************************
写数据 AT24c512Write()
Devaddr 设备地址 addr_h 高位地址 addr_l 低位地址
w_data 需写入的数据 num_w 数据长度
*************************************************/
uchar AT24c512Write(uchar Devaddr, uchar addr_h, uchar addr_l, uchar w_data)
{
uchar temp1,k=0;
while(!twi_start() && k<=10){k++;} //发送起始电平
if(k>10)
return 0; //返回失败(0)
temp1 = 0xA0 | (Devaddr<<1); //设备地址写
k=0;
while(!twi_writebyte(temp1) && k<=10){k++;}
if(k>10)
return 0;
k=0;
while(!twi_writebyte(addr_h) && k<=10){k++;} //写高位地址
if(k>10)
return 0;
k=0;
while(!twi_writebyte(addr_l) && k<=10){k++;} //写低位地址
if(k>10)
return 0;
k=0;
while(!twi_writebyte(w_data) && k<=10){k++;} //写数据
if(k>10)
return 0;
twi_stop(); //发送停止位
return 1; //写数据完成,返回成功(1)
}
/********************************************************
读数据 AT24c512Read()
Devaddr 设备地址 addr_h 高位地址 addr_l 低位地址
r_data 读出的数据 num_r 数据长度
********************************************************/
uchar AT24c512Read(uchar Devaddr, uchar addr_h, uchar addr_l,uchar r_data)
{
uchar temp2,k=0;
while(!twi_start() && k<=10){k++;} //启动起始条件
if(k>10)
return 0;
temp2 = 0xA0 | (Devaddr<<1); //设备地址写
k=0;
while(!twi_writebyte(temp2) && k<=10){k++;}
if(k>10)
return 0;
k=0;
while(!twi_writebyte(addr_h) && k<=10){k++;} //高位地址
if(k>10)
return 0;
k=0;
while(!twi_writebyte(addr_l) && k<=10){k++;} //低位地址
if(k>10)
return 0;
k=0;
while(!twi_start() && k<=10){k++;} //启动起始条件
if(k>10)
return 0;
temp2 = 0xA1 | (Devaddr<<1); //设备地址读
k=0;
while(!twi_writebyte(temp2) && k<=10){k++;}
if(k>10)
return 0;
k=0;
while(!twi_readbyte(r_data,0) && k<=10){k++;} //读数据
if(k>10)
return 0;
twi_stop();
return 1;
}
/***********************************************
timer_init(): 定时器T0,T1初始化
功能:初始化T0,T1;T0
***********************************************/
void timer_init()
{
TCCR1A = 0x00; //工作在普通端口模式
TCCR1B = 0x08; //T1工作在CTC方式,初始化时先令T1的输出比较不工作
TCCR0 = 0x00; //先令T0不工作
TCNT0 = 0x16; //设置T0初始值,1/400节拍为1870us
TCCR2 = 0x00; //先令T2不工作
TCNT2 = 0x07; //设置T2初值,每产生一次溢出中断时间为2000us
TIMSK = 0x51; //使能T0溢出中断,T1输出比较中断, T2溢出中断
}
/******************************
can总线初始化函数
******************************/
void can_init()//can 初始化
{
uchar *p_canaddr;
uchar i,j;
/*for(i=0;i<20;i++)
for(j=0;j<8;j++)
canRbuf[i][j]=0;*/
CAN_CS_0;
CAN_RST_0;
DelayMs(5);
CAN_RST_1;
//硬件复位首先进入BasicCAN mode
//进入复位mode(控制寄存器CR)
p_canaddr = (uchar *)CAN_OFFSET;//CAN0
while((*p_canaddr & 0x01) != 0x01)
{
*p_canaddr = 0x01; //(0)RR=1;关中断
}
//choose PeliCAN mode(时钟分频寄存器CDR)
p_canaddr = (uchar *)(CAN_OFFSET + 31);//CAN 31
do{
*p_canaddr = 0xcf;//(7)can mode=1:PeliCAN; (6)CBP=1:中止输入比较器;
//(5)RXINTEN=0;(3)关闭时钟=1:CLK无效;(2:0)CD2:0=111(fosc)
}while(*p_canaddr != 0xcf);
//设置验收滤波器(包括验收代码寄存器ACRn 和 验收屏蔽寄存器AMRn)
p_canaddr = (uchar*)CAN_OFFSET;//CAN0
for(i=0;i<8;i++)
*(p_canaddr + 16 + i) = 0xff;//ACR=0XFF;AMR=0XFF;
//完全接受
*(p_canaddr + 19) = can_laddr<<3;//local address load into ACR3(ID28:21)
*(p_canaddr + 23) &= 0x07;//AMR3 enable ACR3 to compare data input
//总线定时寄存器1,0(BTR1,0)
//每位时钟频率:fOSC/4*(4+7+1)
p_canaddr = (uchar*)(CAN_OFFSET + 6);//can 6:BTR0
//*p_canaddr = 0x47;
*p_canaddr = 0xC1;
//(7:6)SJW1..0=11同步跳转宽度tSJW=4tSCL;
//(5:0)BRP(5:0)=000001波特率预设值can系统时钟fSCL = fOSC/4;
//*(p_canaddr + 1) = 0XA5;
*(p_canaddr + 1) = 0x17;
//CAN 7 BTR1:(7)SAM=0:单倍采样;
//(6:4)TSEG2(2:0)=001 TSEG2=1tSCL; (3:0)TSEG1(3:0)=0111 tSEG1=7tSCL;
//输出控制寄存器(OCR)
p_canaddr = (uchar*)(CAN_OFFSET + 8);//CAN 8
*p_canaddr = 0XDA;//T1未用 (1:0)OCMODE(1:0)=10正常OUT MODE
//中断使能寄存器(IER)
p_canaddr = (uchar*)(CAN_OFFSET + 4);//CAN 4
*p_canaddr = 0x01;//RIE=1 开接收中断
//进入工作 mode , 单验收滤波器
p_canaddr = (uchar*)CAN_OFFSET;//CAN 0
do{
*p_canaddr = 0x08;//(3)AFM=1单滤波器MODE;(0)RM=0:工作MODE
}while(*p_canaddr != 0x08);
//使能SRAM中断INT2
// EIMSK |= (1<<INT2);
}
/********************************************
can发送程序(标准帧)
can_Saddr:目的地址 canSndbuf[8]:发送缓存区
nums发送字节数
********************************************/
uchar can_sends(uchar Saddr, uchar nums )
{
uchar i;
uchar *p_canaddr;
if(nums>8)
nums = 8;
p_canaddr = (uchar*)(CAN_OFFSET + 2 ); //CAN 2 状态寄存器
if((*p_canaddr & 0x04) == 0x04) //查询发送缓存区状态是否为空(TBS?=1)
{
p_canaddr = (uchar*)(CAN_OFFSET + 16); //CAN 16 帧信息
*p_canaddr = (0x0f & nums); //FF(7)=0标准帧,RTR(6)=0数据帧,DLC3~0(3~0)=1000数据长度=8
p_canaddr++; //can 17
*p_canaddr = (Saddr >> 3); //目的地址
p_canaddr++; //can 18
*p_canaddr = (Saddr << 5);
for(i=0; i<nums; i++) //发送数据
{
p_canaddr++; //can 19~26
*p_canaddr = canSndbuf[i];
//usart_txc(canSndbuf[i]); //调试时比对can和usart发送的数据
}
p_canaddr = (uchar*)(CAN_OFFSET + 1); //can 1 命令寄存器
*p_canaddr = 0x01; //发送请求
return 1;
}
else
return 0;
}
/*********************************************
发送程序(扩展帧)
can_Saddr:目的地址 canSndbuf[8]:发送缓存区
nume发送字节数
*********************************************/
/*uchar can_sende(uchar Saddr,uchar nume)
{
uchar i;
uchar *p_canaddr;
if(nume>8)
nume = 8;
p_canaddr = (uchar*)(CAN_OFFSET + 2); //CAN 2 状态寄存器
if((*p_canaddr & 0x04) == 0x04) //查询发送缓存区状态是否为空(TBS?=1)
{
p_canaddr = (uchar*)(CAN_OFFSET + 16); //CAN 16 帧信息
*p_canaddr = (0x0F & nume) | 0x80; //FF(7)=1扩展帧,RTR=0数据帧,DLC3~0=1000数据长度
p_canaddr++;//can 17 ID28-21
*p_canaddr = can_laddr;//本机地址 Saddr >> 3;
p_canaddr++;//can18 ID20-13
*p_canaddr = comm;//命令号
p_canaddr++;//can19 ID12=0 uend,ID12=1 end; ID11-5:帧计数
*p_canaddr = 0x80;//命令号
p_canaddr++;//can20 ID4-0 目的地址
*p_canaddr = Saddr << 3;
for(i=0;i<nume;i++)//can 21..28 发送数据
{
p_canaddr++;
*p_canaddr = canSbuf[i];
USART_Transmit(canSbuf[i]);
}
p_canaddr = (uchar*)(CAN_OFFSET + 1);//CAN 1
*p_canaddr = 0x01;//发送请求
return 1;
}
else
return 0;
}*/
/********************************************
can总线接收中断服务程序
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -