找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6530|回复: 0
收起左侧

dsPIC30F6014控制DS18B20温度+CAN总线的发送程序

[复制链接]
ID:75926 发表于 2015-4-2 23:16 | 显示全部楼层 |阅读模式
  1. dsPIC30F6014控制DS18B20温度+CAN总线的发送程序
  2. //          1。DS18B20定时采集温度
  3. //          2。温度采集时间间隔用T1定时器控制
  4. //          3。采集到的温度通过CAN总线送另一主机处理

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

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

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


回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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