找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4541|回复: 1
收起左侧

dsPIC30F6014 CAN总线发送功能+DS18B20温度采集

[复制链接]
ID:75926 发表于 2015-4-2 23:18 | 显示全部楼层 |阅读模式
  1. 1。DS18B20定时采集温度
  2. 2。温度采集时间间隔用T1定时器控制
  3. 3。采集到的温度通过CAN总线送另一主机处理
  4. #include <p30f6014.h>             //dsPIC30F6014标准头文件
  5.   _FOSC(0x0ffe5);                 //4倍频晶振,Failsafe 时钟关闭
  6.   _FWDT(WDT_OFF);                 //关闭看门狗定时器
  7.   _FBORPOR(PBOR_OFF & MCLR_EN);   //掉电复位禁止,MCLR复位使能。
  8.   _FGS(CODE_PROT_OFF);            //代码保护禁止
  9. unsigned long int i = 0;
  10. #define  uch unsigned char                     //给unsigned char起别名 uch
  11. # define DQ PORTFbits.RF6                      //定义18B20数据端口
  12. # define DQ_DIR TRISFbits.TRISF6               //定义18B20D口方向寄存器
  13. # define DQ_HIGH() DQ_DIR =1                   //设置数据口为输入
  14. # define DQ_LOW() DQ = 0; DQ_DIR = 0           //设置数据口为输出
  15. #define rs LATBbits.LATB4          //定义LCD控制位(注意这里只能用LATB寄存器,不能直接用PORTB寄存器)
  16. #define rw LATBbits.LATB5
  17. #define e  LATBbits.LATB6
  18.                         
  19. unsigned char __attribute__((address(0x900))) TLV;   //采集到的温度高8位
  20. unsigned char __attribute__((address(0x902))) THV;   //采集到的温度低8位
  21. unsigned char __attribute__((address(0x904))) TZ;    //转换后的温度值整数部分
  22. unsigned char __attribute__((address(0x906))) TX;    //转换后的温度值小数部分
  23. unsigned int  __attribute__((address(0x908))) wd;    //转换后的温度值BCD码形式
  24. unsigned char __attribute__((address(0x9a0))) loop;  //LCD显示次数计数器
  25. //**********************CAN总线初始化*************************
  26. void initcan()
  27. {
  28.     C1CTRLbits.REQOP = 0x4; //请求进入配置模式
  29.     while (C1CTRLbits.OPMODE!=0x4){}  //确认进入配置模式
  30.     C1TX0CON = 0x0003;      //发送0邮箱配置
  31.     C1TX0SID = 0x0020;      //发送0标准标识符,11位
  32.     C1TX0DLC = 0x01c0;      //发送0数据长度,8字节
  33.     C1RX0CON = 0x0000;      //接收0邮箱配置
  34.     C1RX0DLC = 0x0008;      //接收0数据长度,8字节
  35.     C1RXF0SID = 0x0020;     //接收滤波器0标准标识符,11位
  36.     C1RXM0SID = 0xffff;     //接收屏蔽0标准标识符
  37.    C1CFG1bits.SJW=0;  //SJW=1 x TQ
  38.    C1CFG1bits.BRP = 9;      //125K  
  39.    C1CFG2 = 0x03Ac;         //SEG2PH=5;SEG1PH=6;PRSEG=4
  40.     C1CTRLbits.REQOP = 0x0; //请求进入正常模式
  41.     while (C1CTRLbits.OPMODE!=0x0){}  //确认进入正常模式
  42. return;
  43. }      

  44. //**********************延时函数**************************
  45. //延时函数(延时时间为(2+x)us)
  46. void delay(  char x)
  47. {
  48.    unsigned char i;
  49.    for(i=0;i<x;i++);
  50. }
  51. //********************系统初始化函数**********************
  52. void init()
  53. {
  54.   TRISF=0X0000;                                 //先设置18B20口方向为输出
  55.   TRISB=0X0000;                                 //设置B口方向为输出
  56.   TRISD=0X0000;                                 //设置D口方向为输出
  57.   IFS0bits.T1IF=0;                              //先清除定时器中断标志位
  58.   PR1=0XFFFF;                                   //周期定最大
  59.   T1CON=0X0020;                                 //分频比为1:64
  60.   INTCON1=0x0000;
  61.   INTCON2=0x0000;                             //关闭所有中断  
  62. }

  63. //******************复位DS18B20函数*****************************
  64. //主控制器(dsPIC30F6014A)先拉低总线480us,然后释放总线回到高电平
  65. //18B20检测到上升沿后先等待15-60us,然后拉低总线做为复位的应答信号
  66. //主控制器释放总线后到复位结束时间应为480US
  67. reset(void)
  68. {
  69.   char presence=1;
  70.   while(presence)
  71.   {
  72.     DQ_LOW() ;                                //主机拉至低电平
  73.     delay(100);                        
  74.     delay(100);   
  75.     delay(100);   
  76.     delay(100);
  77.     delay(78);                                //以上5条共延时480us
  78.     DQ_HIGH();                                //释放总线等电阻拉高总线,并保持15~60us
  79.     delay(38);                                //延时40us        
  80.     if(DQ==1) presence=1;                     //没有接收到应答信号,继续复位
  81.     else presence=0;                          //接收到应答信号
  82.     delay(100);                        
  83.     delay(100);   
  84.     delay(100);   
  85.     delay(100);
  86.     delay(38);                                //以上5条共延时440us
  87.    }
  88.   }
  89. //****************写18b20写字节函数*****************************
  90. //主控制器写数据1:先把总线拉低,然后在15us内释放总线
  91. //主控制器写数据0:把总线拉低至少60us
  92. //写一位数据至少需要60us
  93. //两位数据之间至少延时1us
  94. void write_byte(uch val)
  95. {
  96. uch i;
  97. uch temp;
  98. for(i=8;i>0;i--)
  99. {
  100.    temp=val&0x01;                            //最低位移出
  101.    DQ_LOW();
  102.    delay(3);                                 //保持拉低5us
  103.    if(temp==1)  DQ_HIGH();                   //如果写1,拉高电平
  104.    delay(58);                                //延时60us
  105.    DQ_HIGH();
  106.    delay(1);                                 //在两位之间插入3us延时
  107.    val=val>>1;                               //右移一位
  108.   }
  109. }
  110. //****************18b20读字节函数********************************
  111. //主控制器把总线拉低至少1US,然后释放
  112. //主控制器读数据1:18B20保持总线状态不变
  113. //主控制器读数据0:18B20检测到总线拉低后继续拉低总线至少60ms
  114. //主控制器在拉低总线后的15us读取总线上的状态
  115. //读取1位数据至少需要60us
  116. uch read_byte(void)
  117. {
  118. uch i;
  119. uch value=0;                                //读出温度
  120. for(i=8;i>0;i--)
  121. {
  122.    value>>=1;
  123.    DQ_LOW();
  124.    delay(1);                                //保持总线拉低3us
  125.    DQ_HIGH();                               //拉至高电平
  126.    delay(5);                                //释放总线后保持7us再读取数据
  127.    if(DQ) value|=0x80;
  128.    delay(48);                               //延时50us,保证每1位的60us延时
  129.   }
  130.   return(value);
  131. }
  132. //*****************启动温度转换函数***************************
  133. void get_temp()
  134. {
  135. int i;
  136. DQ_HIGH();                              
  137. reset();                                 //复位等待从机应答
  138. write_byte(0XCC);                        //忽略ROM匹配
  139. write_byte(0X44);                        //发送温度转化命令  
  140. for(i=0;i<8;i++)
  141.     {
  142.         
  143.       delay(98);                         //确保温度转换完成所需要的时间
  144.     }
  145. reset();                                 //再次复位,等待从机应答
  146. write_byte(0XCC);                        //忽略ROM匹配
  147. write_byte(0XBE);                        //发送读温度命令
  148. TLV=read_byte();                         //读出温度低8
  149. THV=read_byte();                         //读出温度高8位
  150. DQ_HIGH();                               //释放总线
  151. TZ=(TLV>>4)|(THV<<4)&0X3f;               //温度整数部分
  152. TX=TLV<<4;                               //温度小数部分
  153. }
  154. //************************主函数********************************
  155. int main(void)
  156. {
  157.    init();                              //调用系统初始化函数
  158.    initcan();
  159.    LATDbits.LATD0=1;
  160.    LATDbits.LATD1=0;
  161.    while(1)
  162.      {
  163.        TMR1=0XC2F6;                     //定时器初值
  164.        T1CONbits.TON=1;                 //启动定时器
  165.        while(!IFS0bits.T1IF);           //等待0.1s定时到
  166.        IFS0bits.T1IF=0;
  167.        get_temp();                      //调用温度转换函数
  168.       
  169.        C1TX0B1 = TZ;                    
  170.        C1TX0B2 = TX;
  171.        C1TX0B3 = 0x5A5A;                //B3跟B4四字节数据无效,也可做效验用
  172.        C1TX0B4 = 0xa5a5;
  173.        C1TX0CONbits.TXREQ = 1;          //启动发送
  174.        while (C1TX0CONbits.TXREQ==1){} //等待发送完成
  175.        for (i=0;i<2;i++){}
  176.      }
  177. }
复制代码


回复

使用道具 举报

ID:342505 发表于 2018-6-27 16:48 | 显示全部楼层
问一下,你这个CAN发送有没有碰到过TXERR的情况?如果碰到了,怎么解决?谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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