您的位置 首页 设计

根据PIC的LIN总线规划

简介:1.主节点主节点资源:4个按键,采用9600波特率的UART,在发送同步间隔场时用4800!收发芯片:MCP2012.从节点从节点资源:UART,CCP捕…

简介:

1.主节点

主节点资源:4个按键,选用9600波特率的UART,在发送同步距离场时用4800!收发芯片:MCP201

2.从节点

从节点资源:UART,CCP捕捉 首要用接纳引脚状况判别是否同步距离场,用定时器1进行计时判别同步距离场是否合格,判别合格后,用CCP模块捕捉同步头55H,一起核算波特率,之后翻开UART进行数据接纳!

程序如下:

1.MASTER

// LIN 总线规划
//———————————————
// 文件名: MASTER.c
// 版别: V1.0
// 日期: 25/12/06
// 功用: LIN总线主节点
// 编译环境: HiTech PIC C compiler v.8.05
// 运用MCU: PIC16F877
// 通讯速率: 9600
//—————协议阐明———————
//数据发送依照USART办法发送
//Lin协议阐明:
//1.电平界说:
// 显性电平:逻辑0
// 隐性电平:逻辑1
//2.数据组成
// 同步距离场:至少13位的显性电平,以及1个位的界定符(隐性电平)
// 同步场:0x55主机发送,从机经过定时器捕捉办法来计时核算波特率
// 数据场:
// a.标识符场:界说了报文的内容和长度,最高两位是奇偶校验位
// 位5和6是数据长度标识,低四位是地址标识符
// b.指令场:由2.4.8个数据字节组成,外加一个数据校验场
// 保存标识符:(播送标识符)
// “0x3c”主机恳求,用于主机播送指令,一切从机都接纳
// “0x3d”从机呼应,触发一切从机节点次序向主机传送数据
// 第一个数据场的00-7F保存,其他自在分配(程序里没有遵从,试验嘛呵呵)
//———————————————
#include //———————————————
//————–常量界说———————-
#define Key1 RA0
#define Key2 RA1
#define Key3 RA2
#define Key4 RA3
#define CS RB1

#define STATUSIT(avr,s) ((unsigned)(&avr)*8+(s)) //肯定寻址界说
static bit C @ STATUSIT(STATUS,0); //对进位位进行界说
//—————-内存界说——————–
unsigned char send[10]; //界说数据数组
unsigned char Counter; //发送个数计数
//————–函数界说———————-
void Picint(void); //初始化
void KeyScan(void); //键盘扫描
void Work1(void); //事情处理1
void Work2(void); //事情处理2
void Work3(void); //事情处理3
void Work4(void); //事情处理4
void interrupt SDI(void); //中止函数
void Delay(unsigned int m); //延时函数
void Send(void); //数据发送
void SendSync(void); //同步距离场和同步头发送
void SendData(unsigned char asd); //发送数据场
unsigned char CheckSum(unsigned char as); //校验和核算
void qushu();
//*********************************************
//主函数
//*********************************************
void main()
{
Picint();
while(1)
{
KeyScan(); //键盘扫描等候处理
}
}

//*********************************************
//初始化函数
//*********************************************
void Picint()
{
INTCON=0; //中止界说
ADCON1=0x07; //界说A口为数字ioput形式
TRISA0=1; //键盘接口界说
TRISA1=1;
TRISA2=1;
TRISA3=1;
TRISB0=1; //中止界说端口
TRISB1=0; //片选引脚

TXSTA=0x04; //USART模块设置,运用高速波特率设置
RCSTA=0x80; //使能串口,并没有敞开接纳和发送

TRISC7=1; //数据输入
TRISC6=0; //数据发送
CS=1; //片选
RC6=1;
}
//*********************************************
//数据发送 USART
//*********************************************
void Send()
{
//TXEN=1; //发送使能
SendSync(); //发送同步距离场和同步头
SendData(Counter); //发送的字节的数量
TXEN=0; //发送制止
}
//*********************************************
//同步距离场和同步头发送
//*********************************************
void SendSync()
{
SPBRG=0x33; //同步距离场依照4800发送
Delay(20);
TXEN=1;
Delay(20);
TXREG=0x80; //同步距离场
while(1) //等候发送结束
{
if(TXIF==1) break;
}
Delay(150);
SPBRG=0x19; //修正波特率为9600
Delay(50);
TXREG=0x55; //发送同步头,用于从机进行波特率核算
while(1)
{
if(TXIF==1) break;
}
Delay(300); //延时预备发送数据
}
//*********************************************
//发送数据场
//*********************************************
void SendData(unsigned char asd)
{
unsigned char i;
TXREG=send[0]; //发送地址字节
while(1)
{
if(TXIF==1) break;
}
Delay(250); //延时,供从节点判别是否是自己的地址
for(i=0;i {
TXREG=send[i+1]; //发送数据字节,以及校验字节
while(1)
{
if(TXIF==1) break;
}
Delay(100);
}
}
//*********************************************
//校验和核算
//*********************************************
unsigned char CheckSum(unsigned char as)
{
//校验和阐明:
//是一切指令字节的和,可是假如相加的话发生进位位怎进位位加到和的最低位,最终成果取反
//从节点接纳后相同核算指令字节和,然后与校验字节相加,其和有必要等于0xFF;
unsigned char z,y;
y=0;
asm(“bcf _STATUS,0”); //清进位位
for(z=0;z {
y=y+send[z+1];
if(C)
{
C=0; //铲除进位位供下次运用
y=y+1; //假如进位位为1,则加到成果的最低位
}
}
y=~y; //按位取反
return y; //回来校验和
}
//*********************************************
//键盘扫描函数
//*********************************************
void KeyScan()
{
if(Key1)
{
Delay(8000); //延时消抖
if(Key1) //承认键盘按下
{
while(Key1) //等候键盘开释
{}
Work1(); //调用处理事情
}
}
//———————————————-
if(Key2)
{
Delay(8000); //延时消抖
if(Key2) //承认键盘按下
{
while(Key2) //等候键盘开释
{}
Work2(); //调用处理事情
}
}
//———————————————-
if(Key3)
{
Delay(8000); //延时消抖
if(Key3) //承认键盘按下
{
while(Key3) //等候键盘开释
{}
Work3(); //调用处理事情
}
}
//———————————————-
if(Key4)
{
Delay(8000); //延时消抖
if(Key4) //承认键盘按下
{
while(Key4) //等候键盘开释
{}
Work4(); //调用处理事情
}
}
}
//*********************************************
//事情处理
//*********************************************
void Work1()
{
send[0]=0xc1; //地址字节01,加上奇偶校验为c1
send[1]=0x12; //指令字节1
send[2]=0x13; //指令字节2
Counter=3;
send[3]=CheckSum(Counter-1); //校验和核算
Send();
}
//———————————————
void Work2()
{
send[0]=0xc1; //地址字节01,加上奇偶校验为c1
send[1]=0x22; //指令字节1
send[2]=0x23;
Counter=3;
send[3]=CheckSum(Counter-1); //校验和核算
Send();
}
//———————————————
void Work3()
{
send[0]=0xc1; //地址字节01,加上奇偶校验为c1
send[1]=0x32; //指令字节1
send[2]=0x33;
Counter=3;
send[3]=CheckSum(Counter-1); //校验和核算
Send();
}
//———————————————
void Work4()
{
send[0]=0xc1; //地址字节01,加上奇偶校验为c1
send[1]=0x42; //指令字节1
send[2]=0x43;
Counter=3;
send[3]=CheckSum(Counter-1); //校验和核算
Send();
}
//*********************************************
//延时函数
//*********************************************
void Delay( unsigned int m)
{
unsigned int i;
for(i=0;i<=m;i++)
{}
}

2.SLAVE

// Lin总线
//———————————————
// 文件名: slave(mew).c
// 版别: V1.0
// 日期: 13/12/06
// 功用: Lin 总线从节点
// 编译环境: HiTech PIC C compiler v.8.05
// 运用MCU: PIC16F876(主频4M)
// 接纳阐明:
// 首要判别同步距离场:符合要求进行下面操作,不然不予理睬并记载过错
// 同步距离收集合格:收集同步头,主节点发送0x55,接纳5个下降沿用于核算波特率
// 波特率核算成功:串口接纳翻开,进行ID接纳,判别是否自己ID不是抛弃接纳后边数据
// ID校验成功:持续接纳后边数据场,并进行校验,合格则进行相应操作,不合格记载过错
// 初始化,进行下一个同步头接纳
//
//——————————————–
#include //——————————————–
//—————常量界说———————-
#define TSync 1000 //同步距离时刻界说
#define FRest 0 //状况复位0
#define FSync 1 //同步距离场检测
#define FSync1 2 //同步距离场检测状况1
#define FTow 3 //同步头接纳
#define FId 4 //地址字节接纳
#define FData 5 //数据接纳

#define CS RC1 //片选引脚,高有用
#define RFIN RC2 //同步距离场和同步场输入端
#define Jiance RB7 //检测引脚,测验时分用

//————–数据界说———————–
unsigned char Data[9]; //数据接纳数组
bank1 unsigned int TimeData[5]; //CCP1捕捉时刻记载函数

unsigned char RFdata; //状况判别
unsigned char FallCount; //同步头的下降沿计数
unsigned int Sytime; //同步头总时刻保存
unsigned char RFstate; //接纳状况指示
unsigned char Towallow; //波特率核算答应标志
unsigned char DataCount; //接纳数据字节个数寄存器

unsigned char y;

volatile bit IDcheck; //数据校验合格标志
volatile bit Operate; //操作答应标志
volatile bit DatCheck; //数据和校验成功标志

//bank1 unsigned char Stat @ 0x8f; //
unsigned char IDmoment ; //ID号暂时保存
//#define AVR(adr,biti) ((unsigned)(&adr)*8+(biti))
//#define ID0 AVR(Stat,0) //位界说
//#define ID1 AVR(Stat,1)
//#define ID2 AVR(Stat,2)
//#define ID3 AVR(Stat,3)
//#define ID4 AVR(Stat,4)
//#define ID5 AVR(Stat,5)
//#define ID6 AVR(Stat,6)
//#define ID7 AVR(Stat,7)

union
{
struct
{
unsigned b0:1; //0位,冒号后边的是占的位数
unsigned b1:1;
unsigned b2:1;
unsigned b3:1;
unsigned b4:1;
unsigned b5:1;
unsigned b6:1;
unsigned b7:1;
}onebit;
unsigned char allbit;
}all;
#define ID0 all.onebit.b0
#define ID1 all.onebit.b1
#define ID2 all.onebit.b2
#define ID3 all.onebit.b3
#define ID4 all.onebit.b4
#define ID5 all.onebit.b5
#define ID6 all.onebit.b6
#define ID7 all.onebit.b7
#define Stat all.allbit
/*
上面位界说也可以用肯定寻址位操作(但不主张)
或许结构和联合体

运用办法:
all.onebit.b0=1; //给位0置1
all.allbit=0; //字节清0
*/
#define STATUSIT(avr,s) ((unsigned)(&avr)*8+(s)) //肯定寻址界说
static bit C @ STATUSIT(STATUS,0); //对进位位进行界说

union //16位时刻计数器
{
unsigned int Counter;
unsigned char Time[2];
}ASD;
#define TimeL ASD.Time[0]
#define TimeH ASD.Time[1]
//————–函数界说———————–
void Picint(void); //初始化
void Delay(void); //延时
void DataIn(void); //数据输入判别
void interrupt SDI(void); //中止函数
void DataClear(void); //数组清0
void Dispose(void); //数据处理函数
void DataCdc(unsigned char asd); //数据校验
//———————————————
//********************************************
//主函数
//********************************************
void main()
{
Picint();
while(1)
{
DataIn(); //数据查询
if(Operate) //是否答应操作,进行相应操作
{
DataCdc(DataCount); //数据校验是否合格
if(DatCheck)
{
Dispose();
}
}
}
}
//********************************************
//数据处理函数
//********************************************
void Dispose() //试验,并没详细做什么操作
{
if((Data[0]==0x12)&(Data[1]==0x13))
{
RB7=1;
}
if(Data[0]==0x22)
{
RB7=0;
}
}
//********************************************
//数据校验
//********************************************
void DataCdc(unsigned char asd) //核算数据校验和
{
unsigned char x,y;
DatCheck=0;
y=0;
asm(“bcf _STATUS,0”); //清进位位
for(x=0;x<(asd-1);x++)
{
y=y+Data[x];
if(C)
{
C=0;
y=y+1;
}
}
y=y+Data[asd-1];
if(y==0xff) //校验成功
{
DatCheck=1;
}
}
//********************************************
//中止函数
//********************************************
void interrupt SDI() //用捕捉办法进行下降沿计数,核算同步头
{
if(CCP1IE&CCP1IF) //承认中止
{
CCP1IF=0; //清中止标志
TimeL=CCPR1L; //取数
TimeH=CCPR1H; //
TimeData[FallCount]=ASD.Counter; //写入数组
FallCount++;
if(FallCount==5)
{
CCP1CON=0x00; //制止CCP1捕捉
CCP1IE=0; //制止CCP1中止
CCP1IF=0; //清中止标志
FallCount=0;
Towallow=1; //波特率核算答应
TMR1ON=0;
TMR1L=0;
TMR1H=0;
}
}
}
//********************************************
//数据输入
//********************************************
void DataIn()
{
switch(RFstate)
{
case FSync: //同步距离场检测
RFdata=RFIN; //采样值
if(RFdata==0) //下降沿检测
{
TMR1L=0;
TMR1H=0;
TMR1ON=1; //敞开定时器1
RFstate=FSync1; //转向状况1
}
break;

case FSync1:
RFdata=RFIN;
if(RFdata==0)
{
if(TMR1IF) //在很长时刻内假如主机的同步距离场没有完结发生过错
{
TMR1IF=0;
TMR1ON=0;
TMR1L=0;
TMR1H=0;
RFstate=FRest; //状况机复位
}
}
else
{
TMR1ON=0; //封闭定时器
TimeL=TMR1L; //取出计数值
TimeH=TMR1H;
TMR1L=0; //计数器清0
TMR1H=0;
if(ASD.Counter>=TSync)
{
RFstate=FTow; //距离场接纳成功,下面接纳同步头
TMR1ON=1;
CCP1IE=1; //使能CCP1中止
CCP1IF=0; //清中止标志
CCP1CON=0x04; //装备捕捉办法,捕捉下降沿
}
else
{
RFstate=FRest; //不然指向复位
}
}
break;

case FTow: //同步头接纳
if(Towallow)
{
unsigned char i;
// SPBRG=0x19; //波特率设置
// RFstate=FId; //指向ID场接纳
// CREN=1; //使能接纳
Sytime=0;
for(i=0;i<4;i++) //循环核算总数据
{
Sytime=Sytime+(TimeData[i+1]-TimeData[i]);
}
Sytime=Sytime>>3; //除8核算
Sytime=(Sytime>>2)-1;
i=(unsigned char)Sytime;//强制转换为字节型数据,设定波特率
if((i<=30)&(i>=20)) //给定核算规模
{
SPBRG=0x19; //波特率设置
RFstate=FId; //指向ID场接纳
CREN=1; //使能接纳
}
else
{
RFstate=FRest; //状况复位
}
}
break;

case FId:
while(1) //等候数据接纳
{
if(RCIF==1) break;
}
IDmoment=RCREG; //数据读取,清中止标
Stat=IDmoment;
if((Stat&0x0f)==0x01) //判别是否是自己的ID地址,假如是自己的ID地址,校验暂时没加
{
Stat=IDmoment;
if((ID4==0)&(ID5==0))
{
DataCount=3; //两个数据接纳,一起还有1个校验字节
}
if((ID4==1)&(ID5==0))
{
DataCount=3; //两个数据接纳,一起还有1个校验字节
}
if((ID4==0)&(ID5==1))
{
DataCount=5; //四个数据接纳,一起还有1个校验字节
}
if((ID4==1)&(ID5==1))
{
DataCount=9; //八个数据接纳,一起还有1个校验字节
}
RFstate=FData; //指向数据接纳
}
else
{
RFstate=FRest; //复位
}
break;

case FData: //数据接纳
for(y=0;y {
while(1)
{
if(RCIF==1) break;
}
Data[y]=RCREG; //读取一个数据
}
RFstate=FRest; //复位,数据接纳结束
Operate=1; //答应操作

break;

default:
RFstate=FSync; //指向同步头接纳
Towallow=0; //波特率核算制止
FallCount=0;
CCP1CON=0x00; //CCP制止
TXEN=0; //制止发送
CREN=0; //异步形式制止接纳
DataCount=0; //数据长度清0
Operate=0;
}
}
//********************************************
//初始化
//********************************************
void Picint()
{
INTCON=0; //清中止源
GIE=1; //开总中止
PEIE=1; //开外部中止
RCIE=0; //制止串口接纳中止
ADCON1=0x07; //界说A口为数字ioput模
//TRISA= 0xFF; //界说端口输入输出形式
TRISC1=0; //片选输出端口
TRISC2=1; //捕捉模块1输入端

TRISB7=0; //测验运用的输出引脚
RB7=0;

SPBRG=0x19; //界说波特率
TXSTA=0x04; //使能高速波特率,异步形式
RCSTA=0x80; //使能串口,制止接连接纳
TRISC6=1; //串口使能后这两位有必要设置为输入高阻抗状况
TRISC7=1;

T1CON=0x00; //定时器1初始化,用于捕捉功用
TMR1L=0x00;
TMR1H=0x00;
TMR1IE=0; //中止标志以及中止铲除
TMR1IF=0;

CS=1; //片选置高

RFstate=FRest; //状况机复位
Operate;

DataClear(); //数组清0
}
//********************************************
//数组清0 函数
//********************************************
void DataClear()
{
for(y=0;y<9;y++)
{
Data[y]=0;
}
}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/sheji/266980.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部