<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于PIC的LIN總線設(shè)計

          基于PIC的LIN總線設(shè)計

          作者: 時間:2016-11-18 來源:網(wǎng)絡(luò) 收藏
          簡介:

          1.主節(jié)點

          本文引用地址:http://www.ex-cimer.com/article/201611/315945.htm

          主節(jié)點資源:4個按鍵,采用9600波特率的UART,在發(fā)送同步間隔場時用4800!收發(fā)芯片:MCP201

          2.從節(jié)點

          從節(jié)點資源:UART,CCP捕捉 首先用接收引腳狀態(tài)判斷是否同步間隔場,用定時器1進行計時判斷同步間隔場是否合格,判斷合格后,用CCP模塊捕捉同步頭55H,同時計算波特率,之后打開UART進行數(shù)據(jù)接收!

          程序如下:

          1.MASTER

          // LIN 總線設(shè)計
          //---------------------------------------------
          // 文件名: MASTER.c
          // 版本: V1.0
          // 日期: 25/12/06
          // 功能: LIN總線主節(jié)點
          // 編譯環(huán)境: HiTech PIC C compiler v.8.05
          // 使用MCU: PIC16F877
          // 通信速率: 9600
          //---------------協(xié)議說明---------------------
          //數(shù)據(jù)發(fā)送按照USART方式發(fā)送
          //Lin協(xié)議說明:
          //1.電平定義:
          // 顯性電平:邏輯0
          // 隱性電平:邏輯1
          //2.數(shù)據(jù)組成
          // 同步間隔場:至少13位的顯性電平,以及1個位的界定符(隱性電平)
          // 同步場:0x55主機發(fā)送,從機通過定時器捕捉方式來計時計算波特率
          // 數(shù)據(jù)場:
          // a.標識符場:定義了報文的內(nèi)容和長度,最高兩位是奇偶校驗位
          // 位5和6是數(shù)據(jù)長度標識,低四位是地址標識符
          // b.命令場:由2.4.8個數(shù)據(jù)字節(jié)組成,外加一個數(shù)據(jù)校驗場
          // 保留標識符:(廣播標識符)
          // "0x3c"主機請求,用于主機廣播命令,所有從機都接收
          // "0x3d"從機響應(yīng),觸發(fā)所有從機節(jié)點順序向主機傳送數(shù)據(jù)
          // 第一個數(shù)據(jù)場的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); //對進位位進行定義
          //----------------內(nèi)存定義--------------------
          unsigned char send[10]; //定義數(shù)據(jù)數(shù)組
          unsigned char Counter; //發(fā)送個數(shù)計數(shù)
          //--------------函數(shù)定義----------------------
          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); //中斷函數(shù)
          void Delay(unsigned int m); //延時函數(shù)
          void Send(void); //數(shù)據(jù)發(fā)送
          void SendSync(void); //同步間隔場和同步頭發(fā)送
          void SendData(unsigned char asd); //發(fā)送數(shù)據(jù)場
          unsigned char CheckSum(unsigned char as); //校驗和計算
          void qushu();
          //*********************************************
          //主函數(shù)
          //*********************************************
          void main()
          {
          Picint();
          while(1)
          {
          KeyScan(); //鍵盤掃描等待處理
          }
          }

          //*********************************************
          //初始化函數(shù)
          //*********************************************
          void Picint()
          {
          INTCON=0; //中斷定義
          ADCON1=0x07; //定義A口為數(shù)字ioput模式
          TRISA0=1; //鍵盤接口定義
          TRISA1=1;
          TRISA2=1;
          TRISA3=1;
          TRISB0=1; //中斷定義端口
          TRISB1=0; //片選引腳

          TXSTA=0x04; //USART模塊設(shè)置,使用高速波特率設(shè)置
          RCSTA=0x80; //使能串口,并沒有開啟接收和發(fā)送

          TRISC7=1; //數(shù)據(jù)輸入
          TRISC6=0; //數(shù)據(jù)發(fā)送
          CS=1; //片選
          RC6=1;
          }
          //*********************************************
          //數(shù)據(jù)發(fā)送 USART
          //*********************************************
          void Send()
          {
          //TXEN=1; //發(fā)送使能
          SendSync(); //發(fā)送同步間隔場和同步頭
          SendData(Counter); //發(fā)送的字節(jié)的數(shù)量
          TXEN=0; //發(fā)送禁止
          }
          //*********************************************
          //同步間隔場和同步頭發(fā)送
          //*********************************************
          void SendSync()
          {
          SPBRG=0x33; //同步間隔場按照4800發(fā)送
          Delay(20);
          TXEN=1;
          Delay(20);
          TXREG=0x80; //同步間隔場
          while(1) //等待發(fā)送完畢
          {
          if(TXIF==1) break;
          }
          Delay(150);
          SPBRG=0x19; //修改波特率為9600
          Delay(50);
          TXREG=0x55; //發(fā)送同步頭,用于從機進行波特率計算
          while(1)
          {
          if(TXIF==1) break;
          }
          Delay(300); //延時準備發(fā)送數(shù)據(jù)
          }
          //*********************************************
          //發(fā)送數(shù)據(jù)場
          //*********************************************
          void SendData(unsigned char asd)
          {
          unsigned char i;
          TXREG=send[0]; //發(fā)送地址字節(jié)
          while(1)
          {
          if(TXIF==1) break;
          }
          Delay(250); //延時,供從節(jié)點判斷是否是自己的地址
          for(i=0;i {
          TXREG=send[i+1]; //發(fā)送數(shù)據(jù)字節(jié),以及校驗字節(jié)
          while(1)
          {
          if(TXIF==1) break;
          }
          Delay(100);
          }
          }
          //*********************************************
          //校驗和計算
          //*********************************************
          unsigned char CheckSum(unsigned char as)
          {
          //校驗和說明:
          //是所有命令字節(jié)的和,但是如果相加的話產(chǎn)生進位位怎進位位加到和的最低位,最后結(jié)果取反
          //從節(jié)點接收后同樣計算命令字節(jié)和,而后與校驗字節(jié)相加,其和必須等于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,則加到結(jié)果的最低位
          }
          }
          y=~y; //按位取反
          return y; //返回校驗和
          }
          //*********************************************
          //鍵盤掃描函數(shù)
          //*********************************************
          void KeyScan()
          {
          if(Key1)
          {
          Delay(8000); //延時消抖
          if(Key1) //確認鍵盤按下
          {
          while(Key1) //等待鍵盤釋放
          {}
          Work1(); //調(diào)用處理事件
          }
          }
          //----------------------------------------------
          if(Key2)
          {
          Delay(8000); //延時消抖
          if(Key2) //確認鍵盤按下
          {
          while(Key2) //等待鍵盤釋放
          {}
          Work2(); //調(diào)用處理事件
          }
          }
          //----------------------------------------------
          if(Key3)
          {
          Delay(8000); //延時消抖
          if(Key3) //確認鍵盤按下
          {
          while(Key3) //等待鍵盤釋放
          {}
          Work3(); //調(diào)用處理事件
          }
          }
          //----------------------------------------------
          if(Key4)
          {
          Delay(8000); //延時消抖
          if(Key4) //確認鍵盤按下
          {
          while(Key4) //等待鍵盤釋放
          {}
          Work4(); //調(diào)用處理事件
          }
          }
          }
          //*********************************************
          //事件處理
          //*********************************************
          void Work1()
          {
          send[0]=0xc1; //地址字節(jié)01,加上奇偶校驗為c1
          send[1]=0x12; //命令字節(jié)1
          send[2]=0x13; //命令字節(jié)2
          Counter=3;
          send[3]=CheckSum(Counter-1); //校驗和計算
          Send();
          }
          //---------------------------------------------
          void Work2()
          {
          send[0]=0xc1; //地址字節(jié)01,加上奇偶校驗為c1
          send[1]=0x22; //命令字節(jié)1
          send[2]=0x23;
          Counter=3;
          send[3]=CheckSum(Counter-1); //校驗和計算
          Send();
          }
          //---------------------------------------------
          void Work3()
          {
          send[0]=0xc1; //地址字節(jié)01,加上奇偶校驗為c1
          send[1]=0x32; //命令字節(jié)1
          send[2]=0x33;
          Counter=3;
          send[3]=CheckSum(Counter-1); //校驗和計算
          Send();
          }
          //---------------------------------------------
          void Work4()
          {
          send[0]=0xc1; //地址字節(jié)01,加上奇偶校驗為c1
          send[1]=0x42; //命令字節(jié)1
          send[2]=0x43;
          Counter=3;
          send[3]=CheckSum(Counter-1); //校驗和計算
          Send();
          }
          //*********************************************
          //延時函數(shù)
          //*********************************************
          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 總線從節(jié)點
          // 編譯環(huán)境: HiTech PIC C compiler v.8.05
          // 使用MCU: PIC16F876(主頻4M)
          // 接收說明:
          // 首先判斷同步間隔場:符合要求進行下面操作,否則不予理睬并記錄錯誤
          // 同步間隔采集合格:采集同步頭,主節(jié)點發(fā)送0x55,接收5個下降沿用于計算波特率
          // 波特率計算成功:串口接收打開,進行ID接收,判斷是否自己ID不是放棄接收后面數(shù)據(jù)
          // ID校驗成功:繼續(xù)接收后面數(shù)據(jù)場,并進行校驗,合格則進行相應(yīng)操作,不合格記錄錯誤
          // 初始化,進行下一個同步頭接收
          //
          //--------------------------------------------
          #include
          //--------------------------------------------
          //---------------常量定義----------------------
          #define TSync 1000 //同步間隔時間定義
          #define FRest 0 //狀態(tài)復(fù)位0
          #define FSync 1 //同步間隔場檢測
          #define FSync1 2 //同步間隔場檢測狀態(tài)1
          #define FTow 3 //同步頭接收
          #define FId 4 //地址字節(jié)接收
          #define FData 5 //數(shù)據(jù)接收

          #define CS RC1 //片選引腳,高有效
          #define RFIN RC2 //同步間隔場和同步場輸入端
          #define Jiance RB7 //檢測引腳,測試時候用


          //--------------數(shù)據(jù)定義-----------------------
          unsigned char Data[9]; //數(shù)據(jù)接收數(shù)組
          bank1 unsigned int TimeData[5]; //CCP1捕捉時間記錄函數(shù)

          unsigned char RFdata; //狀態(tài)判斷
          unsigned char FallCount; //同步頭的下降沿計數(shù)
          unsigned int Sytime; //同步頭總時間保存
          unsigned char RFstate; //接收狀態(tài)指示
          unsigned char Towallow; //波特率計算允許標志
          unsigned char DataCount; //接收數(shù)據(jù)字節(jié)個數(shù)寄存器

          unsigned char y;

          volatile bit IDcheck; //數(shù)據(jù)校驗合格標志
          volatile bit Operate; //操作允許標志
          volatile bit DatCheck; //數(shù)據(jù)和校驗成功標志

          //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位,冒號后面的是占的位數(shù)
          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
          /*
          上面位定義也可以用絕對尋址位操作(但不建議)
          或者結(jié)構(gòu)和聯(lián)合體

          應(yīng)用方法:
          all.onebit.b0=1; //給位0置1
          all.allbit=0; //字節(jié)清0
          */
          #define STATUSIT(avr,s) ((unsigned)(&avr)*8+(s)) //絕對尋址定義
          static bit C @ STATUSIT(STATUS,0); //對進位位進行定義

          union //16位時間計數(shù)器
          {
          unsigned int Counter;
          unsigned char Time[2];
          }ASD;
          #define TimeL ASD.Time[0]
          #define TimeH ASD.Time[1]
          //--------------函數(shù)定義-----------------------
          void Picint(void); //初始化
          void Delay(void); //延時
          void DataIn(void); //數(shù)據(jù)輸入判斷
          void interrupt SDI(void); //中斷函數(shù)
          void DataClear(void); //數(shù)組清0
          void Dispose(void); //數(shù)據(jù)處理函數(shù)
          void DataCdc(unsigned char asd); //數(shù)據(jù)校驗
          //---------------------------------------------
          //********************************************
          //主函數(shù)
          //********************************************
          void main()
          {
          Picint();
          while(1)
          {
          DataIn(); //數(shù)據(jù)查詢
          if(Operate) //是否允許操作,進行相應(yīng)操作
          {
          DataCdc(DataCount); //數(shù)據(jù)校驗是否合格
          if(DatCheck)
          {
          Dispose();
          }
          }
          }
          }
          //********************************************
          //數(shù)據(jù)處理函數(shù)
          //********************************************
          void Dispose() //實驗,并沒具體做什么操作
          {
          if((Data[0]==0x12)&(Data[1]==0x13))
          {
          RB7=1;
          }
          if(Data[0]==0x22)
          {
          RB7=0;
          }
          }
          //********************************************
          //數(shù)據(jù)校驗
          //********************************************
          void DataCdc(unsigned char asd) //計算數(shù)據(jù)校驗和
          {
          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;
          }
          }
          //********************************************
          //中斷函數(shù)
          //********************************************
          void interrupt SDI() //用捕捉方式進行下降沿計數(shù),計算同步頭
          {
          if(CCP1IE&CCP1IF) //確認中斷
          {
          CCP1IF=0; //清中斷標志
          TimeL=CCPR1L; //取數(shù)
          TimeH=CCPR1H; //
          TimeData[FallCount]=ASD.Counter; //寫入數(shù)組
          FallCount++;
          if(FallCount==5)
          {
          CCP1CON=0x00; //禁止CCP1捕捉
          CCP1IE=0; //禁止CCP1中斷
          CCP1IF=0; //清中斷標志
          FallCount=0;
          Towallow=1; //波特率計算允許
          TMR1ON=0;
          TMR1L=0;
          TMR1H=0;
          }
          }
          }
          //********************************************
          //數(shù)據(jù)輸入
          //********************************************
          void DataIn()
          {
          switch(RFstate)
          {
          case FSync: //同步間隔場檢測
          RFdata=RFIN; //采樣值
          if(RFdata==0) //下降沿檢測
          {
          TMR1L=0;
          TMR1H=0;
          TMR1ON=1; //開啟定時器1
          RFstate=FSync1; //轉(zhuǎn)向狀態(tài)1
          }
          break;

          case FSync1:
          RFdata=RFIN;
          if(RFdata==0)
          {
          if(TMR1IF) //在很長時間內(nèi)如果主機的同步間隔場沒有完成產(chǎn)生錯誤
          {
          TMR1IF=0;
          TMR1ON=0;
          TMR1L=0;
          TMR1H=0;
          RFstate=FRest; //狀態(tài)機復(fù)位
          }
          }
          else
          {
          TMR1ON=0; //關(guān)閉定時器
          TimeL=TMR1L; //取出計數(shù)值
          TimeH=TMR1H;
          TMR1L=0; //計數(shù)器清0
          TMR1H=0;
          if(ASD.Counter>=TSync)
          {
          RFstate=FTow; //間隔場接收成功,下面接收同步頭
          TMR1ON=1;
          CCP1IE=1; //使能CCP1中斷
          CCP1IF=0; //清中斷標志
          CCP1CON=0x04; //配置捕捉方式,捕捉下降沿
          }
          else
          {
          RFstate=FRest; //否則指向復(fù)位
          }
          }
          break;

          case FTow: //同步頭接收
          if(Towallow)
          {
          unsigned char i;
          // SPBRG=0x19; //波特率設(shè)置
          // RFstate=FId; //指向ID場接收
          // CREN=1; //使能接收
          Sytime=0;
          for(i=0;i<4;i++) //循環(huán)計算總數(shù)據(jù)
          {
          Sytime=Sytime+(TimeData[i+1]-TimeData[i]);
          }
          Sytime=Sytime>>3; //除8計算
          Sytime=(Sytime>>2)-1;
          i=(unsigned char)Sytime;//強制轉(zhuǎn)換為字節(jié)型數(shù)據(jù),設(shè)定波特率
          if((i<=30)&(i>=20)) //給定計算范圍
          {
          SPBRG=0x19; //波特率設(shè)置
          RFstate=FId; //指向ID場接收
          CREN=1; //使能接收
          }
          else
          {
          RFstate=FRest; //狀態(tài)復(fù)位
          }
          }
          break;

          case FId:
          while(1) //等待數(shù)據(jù)接收
          {
          if(RCIF==1) break;
          }
          IDmoment=RCREG; //數(shù)據(jù)讀取,清中斷標
          Stat=IDmoment;
          if((Stat&0x0f)==0x01) //判斷是否是自己的ID地址,如果是自己的ID地址,校驗暫時沒加
          {
          Stat=IDmoment;
          if((ID4==0)&(ID5==0))
          {
          DataCount=3; //兩個數(shù)據(jù)接收,同時還有1個校驗字節(jié)
          }
          if((ID4==1)&(ID5==0))
          {
          DataCount=3; //兩個數(shù)據(jù)接收,同時還有1個校驗字節(jié)
          }
          if((ID4==0)&(ID5==1))
          {
          DataCount=5; //四個數(shù)據(jù)接收,同時還有1個校驗字節(jié)
          }
          if((ID4==1)&(ID5==1))
          {
          DataCount=9; //八個數(shù)據(jù)接收,同時還有1個校驗字節(jié)
          }
          RFstate=FData; //指向數(shù)據(jù)接收
          }
          else
          {
          RFstate=FRest; //復(fù)位
          }
          break;

          case FData: //數(shù)據(jù)接收
          for(y=0;y {
          while(1)
          {
          if(RCIF==1) break;
          }
          Data[y]=RCREG; //讀取一個數(shù)據(jù)
          }
          RFstate=FRest; //復(fù)位,數(shù)據(jù)接收完畢
          Operate=1; //允許操作

          break;

          default:
          RFstate=FSync; //指向同步頭接收
          Towallow=0; //波特率計算禁止
          FallCount=0;
          CCP1CON=0x00; //CCP禁止
          TXEN=0; //禁止發(fā)送
          CREN=0; //異步模式禁止接收
          DataCount=0; //數(shù)據(jù)長度清0
          Operate=0;
          }
          }
          //********************************************
          //初始化
          //********************************************
          void Picint()
          {
          INTCON=0; //清中斷源
          GIE=1; //開總中斷
          PEIE=1; //開外部中斷
          RCIE=0; //禁止串口接收中斷
          ADCON1=0x07; //定義A口為數(shù)字ioput模
          //TRISA= 0xFF; //定義端口輸入輸出模式
          TRISC1=0; //片選輸出端口
          TRISC2=1; //捕捉模塊1輸入端

          TRISB7=0; //測試使用的輸出引腳
          RB7=0;

          SPBRG=0x19; //定義波特率
          TXSTA=0x04; //使能高速波特率,異步模式
          RCSTA=0x80; //使能串口,禁止連續(xù)接收
          TRISC6=1; //串口使能后這兩位必須設(shè)置為輸入高阻抗狀態(tài)
          TRISC7=1;

          T1CON=0x00; //定時器1初始化,用于捕捉功能
          TMR1L=0x00;
          TMR1H=0x00;
          TMR1IE=0; //中斷標志以及中斷清除
          TMR1IF=0;

          CS=1; //片選置高

          RFstate=FRest; //狀態(tài)機復(fù)位
          Operate;

          DataClear(); //數(shù)組清0
          }
          //********************************************
          //數(shù)組清0 函數(shù)
          //********************************************
          void DataClear()
          {
          for(y=0;y<9;y++)
          {
          Data[y]=0;
          }
          }



          關(guān)鍵詞: PICLIN總

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();