找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2592|回复: 0
打印 上一主题 下一主题
收起左侧

LIN总线MC9S12XS128发送与接收源程序

[复制链接]
跳转到指定楼层
楼主
ID:381982 发表于 2018-8-2 09:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
文件在附件
LIN接收.rar (243.82 KB, 下载次数: 40)
LIN发送.rar (362.66 KB, 下载次数: 30)

单片机源程序如下:
  1. /*---------------------------------------------------------*/
  2. /************************************************************
  3. 飞翔科技MC9S12XS128汽车电子开发板
  4. ************************************************************/
  5. /*---------------------------------------------------------*/
  6. #include <hidef.h>      /* common defines and macros */
  7. #include "derivative.h"      /* derivative-specific definitions */

  8. #define BUZZ PORTK_PK5
  9. #define BUZZ_dir DDRK_DDRK5
  10. #define LEDCPU PORTK_PK4
  11. #define LEDCPU_dir DDRK_DDRK4
  12. #define  BUS_CLOCK                   32000000           //总线频率
  13. #define  OSC_CLOCK                   16000000           //晶振频率
  14. #define  BAUD 9600                   //串口波特率

  15. #define BIT(A,B)      ((A>>B)&0x01)   // A 为变量
  16.                                       // B 表示A中的第几位
  17. #define     ID         0x30           // ID场值为0x30
  18. #define     EN         PTM_PTM6     //LIN使能
  19. #define     EN_dir     DDRM_DDRM6

  20. unsigned int x=0;
  21. Bool a;
  22.                                       
  23. struct message {
  24.   unsigned char identifier;
  25.   unsigned char data[8];
  26. };

  27. struct message msg_send;
  28. struct message msg_get;

  29. // 定义LIN状态
  30. enum lin_state { IDLE, _BREAK, SYNCH, PROTECTED_IDENTIFIER, DATA0, DATA1,
  31.                  DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, CHECKSUM };

  32. // 定义帧结构体
  33. struct frame {
  34.   unsigned char protected_id;
  35.   unsigned char data[8];
  36.   unsigned char check;
  37.   enum lin_state state;
  38.   unsigned char error;
  39. };

  40. struct frame frame_send,frame_receive;

  41. /*************************************************************/
  42. /*                      初始化锁相环                         */
  43. /*************************************************************/
  44. void INIT_PLL(void)
  45. {
  46.     CLKSEL &= 0x7f;       //set OSCCLK as sysclk
  47.     PLLCTL &= 0x8F;       //Disable PLL circuit
  48.     CRGINT &= 0xDF;
  49.    
  50.     #if(BUS_CLOCK == 40000000)
  51.       SYNR = 0x44;
  52.     #elif(BUS_CLOCK == 32000000)
  53.       SYNR = 0x43;     
  54.     #elif(BUS_CLOCK == 24000000)
  55.       SYNR = 0x42;
  56.     #endif

  57.     REFDV = 0x81;         //PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+1)=64MHz ,fbus=32M
  58.     PLLCTL =PLLCTL|0x70;  //Enable PLL circuit
  59.     asm NOP;
  60.     asm NOP;
  61.     while(!(CRGFLG&0x08)); //PLLCLK is Locked already
  62.     CLKSEL |= 0x80;        //set PLLCLK as sysclk
  63. }

  64. /************************************************************/
  65. /*                    初始化ECT模块                         */
  66. /************************************************************/
  67. void initialize_ect(void){
  68.   TSCR1_TFFCA = 1;  // 定时器标志位快速清除
  69.   TSCR1_TEN = 1;    // 定时器使能位. 1=允许定时器正常工作; 0=使主定时器不起作用(包括计数器)
  70.   TIOS  = 0xff;      //指定所有通道为输出比较方式
  71.   TCTL1 = 0x00;            // 后四个通道设置为定时器与输出引脚断开
  72.   TCTL2 = 0x00;     // 前四个通道设置为定时器与输出引脚断开
  73.   TIE   = 0x00;     // 禁止所有通道定时中断
  74.   TSCR2 = 0x07;            // 预分频系数pr2-pr0:111,,时钟周期为4us,
  75.   TFLG1 = 0xff;            // 清除各IC/OC中断标志位
  76.   TFLG2 = 0xff;     // 清除自由定时器中断标志位
  77. }

  78. /*************************************************************/
  79. /*                        初始化LIN                          */
  80. /*************************************************************/
  81. void INIT_LIN(void)
  82. {
  83.   unsigned char i;
  84.   SCI0BD = BUS_CLOCK/16/BAUD;   //设置SCI0波特率为9600  
  85.   SCI0CR1 = 0x00;        //设置SCI0为正常模式,八位数据位,无奇偶校验
  86.   SCI0CR2 = 0x2c;        //允许接收和发送数据,允许接收中断功能
  87.   SCI0SR2_BRK13 = 1;  
  88.   frame_send.protected_id=0;
  89.   frame_send.state=IDLE;
  90.   frame_send.error=0;
  91.   frame_send.check=0;
  92.   for (i=0;i<8;i++)
  93.     frame_send.data[i]=0;
  94.   EN_dir=1;
  95.   EN=1;
  96. }



  97. /*************************************************************/
  98. /*                     计算奇偶校验位                        */
  99. /*************************************************************/
  100. unsigned char LINCalcParity(unsigned char id)
  101. {
  102.   unsigned char parity, p0,p1;
  103.   parity=id;
  104.   p0=(BIT(parity,0)^BIT(parity,1)^BIT(parity,2)^BIT(parity,4))<<6;     //偶校验位
  105.   p1=(!(BIT(parity,1)^BIT(parity,3)^BIT(parity,4)^BIT(parity,5)))<<7;  //奇校验位
  106.   parity|=(p0|p1);
  107.   return parity;
  108. }

  109. /*************************************************************/
  110. /*                       计算和校验位                        */
  111. /*************************************************************/
  112. unsigned char LINCalcChecksum(unsigned char *data)         
  113. {
  114.   unsigned int sum = 0;
  115.   unsigned char i;

  116.   for(i = 0; i < 8; i++)
  117.   {
  118.     sum += data[i];
  119.     if(sum&0xFF00)
  120.       sum = (sum&0x00FF) + 1;
  121.   }
  122.   sum ^= 0x00FF;         
  123.   return (unsigned char)sum;
  124. }

  125. /*************************************************************/
  126. /*                       发送检测函数                        */
  127. /*************************************************************/
  128. Bool LINCheckSend(enum lin_state status, unsigned char val)
  129. {
  130.   // 等待串口数据接收到为止  
  131.   while(frame_send.state < status)
  132.      if(frame_send.error)
  133.      return(FALSE);
  134.    
  135.   switch(status)
  136.   {
  137.     case _BREAK:
  138.     case SYNCH:
  139.       break;
  140.       
  141.     case PROTECTED_IDENTIFIER:
  142.       if(frame_send.protected_id != val)
  143.         return(FALSE);
  144.       break;
  145.         
  146.     case DATA0:
  147.     case DATA1:
  148.     case DATA2:
  149.     case DATA3:
  150.     case DATA4:
  151.     case DATA5:
  152.     case DATA6:
  153.     case DATA7:
  154.       if(frame_send.data[status-DATA0] != val)
  155.         return(FALSE);
  156.       break;
  157.         
  158.     case CHECKSUM:
  159.       if(frame_send.check != val)
  160.         return(FALSE);
  161.       break;
  162.   }
  163.   return(TRUE);
  164. }

  165. /*************************************************************/
  166. /*                     LIN发送字节函数                       */
  167. /*************************************************************/
  168. Bool LINSendChar(unsigned char ch)
  169. {
  170.   while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  171.   SCI0DRL = ch;
  172.   return(TRUE);
  173. }

  174. /*************************************************************/
  175. /*                      LIN发送间隔场                        */
  176. /*************************************************************/
  177. Bool LINSendbreak(void)
  178. {
  179.   while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  180.   SCI0CR2_SBK = 1;           //队列待发送的中止字符
  181.   SCI0CR2_SBK = 0;           //返回正常发送操作
  182.   return(TRUE);
  183. }

  184. /*************************************************************/
  185. /*                     LIN发送信息函数                       */
  186. /*************************************************************/
  187. Bool LINSendMsg(void)
  188. {
  189.   unsigned char check_sum, parity_id, i;
  190.   
  191.   frame_send.error = 0;
  192.   
  193.     // 发送间隔场
  194.     if(!LINSendbreak())
  195.       return(FALSE);
  196.     // 检查间隔场发送
  197.     if(!LINCheckSend(_BREAK,0x00))
  198.       return(FALSE);      
  199.     // 发送同步场
  200.     if(!LINSendChar(0x55))
  201.       return(FALSE);
  202.     // 检查同步场发送
  203.     if(!LINCheckSend(SYNCH,0x55))
  204.       return(FALSE);
  205.     // 计算奇偶校验
  206.     parity_id=LINCalcParity(msg_send.identifier);
  207.     // 发送标识符场
  208.     if(!LINSendChar(parity_id))
  209.       return(FALSE);
  210.     // 检查标识符场发送
  211.     if(!LINCheckSend(PROTECTED_IDENTIFIER, parity_id))
  212.       return(FALSE);  
  213.    
  214.     for(i=0; i < 8; i++)
  215.     {
  216.       // 发送数据场
  217.       if(!LINSendChar(msg_send.data[i]))
  218.         return(FALSE);
  219.       // 检查数据场发送
  220.       if(!LINCheckSend(DATA0+i, msg_send.data[i]))
  221.         return(FALSE);
  222.     }
  223.     check_sum = LINCalcChecksum(msg_send.data);
  224.     // 发送校验和场
  225.     if(!LINSendChar(check_sum))
  226.       return(FALSE);
  227.     // 检查校验和场发送
  228.     if(!LINCheckSend(CHECKSUM, check_sum))
  229.      return(FALSE);  
  230.     frame_send.state = IDLE;
  231.   return(TRUE);
  232. }

  233. /*************************************************************/
  234. /*                     LIN接收字节函数                       */
  235. /*************************************************************/
  236. Bool LINGetChar(void)
  237. {
  238.   unsigned volatile char ch;
  239.   
  240.   // LIN接收通道状态
  241.   switch(frame_send.state)
  242.   {
  243.     case IDLE:
  244.       if(!(SCI0SR1&0x22))
  245.         return(FALSE);  
  246.       if(SCI0DRL)
  247.         return(FALSE);
  248.       break;
  249.     case _BREAK:
  250.       if(!(SCI0SR1&0x20))
  251.         return(FALSE);
  252.       if(SCI0DRL != 0x55)
  253.         return(FALSE);   
  254.       break;  
  255.     case SYNCH:
  256.       if(!(SCI0SR1&0x20))
  257.         return(FALSE);
  258.       ch = SCI0DRL;
  259.       frame_send.protected_id = ch;
  260.       break;   
  261.     case PROTECTED_IDENTIFIER:
  262.     case DATA0:
  263.     case DATA1:
  264.     case DATA2:
  265.     case DATA3:
  266.     case DATA4:
  267.     case DATA5:
  268.     case DATA6:
  269.       if(!(SCI0SR1&0x20))
  270.         return(FALSE);
  271.       ch = SCI0DRL;
  272.       frame_send.data[frame_send.state-PROTECTED_IDENTIFIER] = ch;
  273.       break;
  274.     case DATA7:
  275.       if(!(SCI0SR1&0x20))
  276.         return(FALSE);
  277.       ch = SCI0DRL;
  278.       frame_send.check = ch;
  279.       break;
  280.     case CHECKSUM:
  281.       return(FALSE);  
  282.   }
  283.   frame_send.state+=1;
  284.   return(TRUE);
  285. }

  286. /*************************************************************/
  287. /*                         延时函数                          */
  288. /*************************************************************/
  289. void delay1ms(unsigned int n)
  290. {
  291.     unsigned int i;
  292.     for(i=0;i<n;i++)
  293.     {
  294.         TFLG1_C0F = 1;              //清除标志位
  295.         TC0 = TCNT + 250;             //设置输出比较时间为1ms
  296.         while(TFLG1_C0F == 0);      //等待,直到发生输出比较事件
  297.     }
  298. }


  299. /*************************************************************/
  300. /*                    LIN检查发送的数据                      */
  301. /*************************************************************/
  302. #pragma CODE_SEG __NEAR_SEG NON_BANKED
  303. interrupt void LINreceive(void)
  304. {
  305.   if(!LINGetChar())
  306.   {
  307.     BUZZ=1;
  308.     frame_send.error = 1;
  309.     frame_send.state = IDLE;
  310.   }
  311. }
  312. #pragma CODE_SEG DEFAULT


  313. /*************************************************************/
  314. /*                           主函数                          */
  315. /*************************************************************/
  316. void main(void) {
  317.   DisableInterrupts;
  318.   INIT_PLL();
  319.   initialize_ect();
  320.   INIT_LIN();
  321.   LEDCPU_dir=1;
  322.   LEDCPU=0;
  323.   BUZZ_dir=1;
  324.   BUZZ=0;
  325.         EnableInterrupts;

  326.   msg_send.identifier = ID;    // 标识符
  327.   msg_send.data[0] = 'F';      // 数据  
  328.   msg_send.data[1] = 'R';
  329.   msg_send.data[2] = 'E';
  330.   msg_send.data[3] = 'E';
  331.   msg_send.data[4] = 'F';
  332.   msg_send.data[5] = 'L';
  333.   msg_send.data[6] = 'Y';
  334.   msg_send.data[7] = '!';
  335.   frame_send.state = IDLE;

  336.   for(;;)
  337.   {
  338.       delay1ms(500);
  339.       a = LINSendMsg();      //LIN发送数据
  340.       if(a)
  341.          LEDCPU=~LEDCPU;
  342.       else
  343.          BUZZ=1;
  344.   }
  345. }
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表