基于PIC的LIN总线设计
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++)
{}
}
PICLIN总 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)