标题:
dsPIC30F6014控制DS18B20温度+CAN总线的发送程序
[打印本页]
作者:
xiaos
时间:
2015-4-2 23:16
标题:
dsPIC30F6014控制DS18B20温度+CAN总线的发送程序
dsPIC30F6014控制DS18B20温度+CAN总线的发送程序
// 1。DS18B20定时采集温度
// 2。温度采集时间间隔用T1定时器控制
// 3。采集到的温度通过CAN总线送另一主机处理
#include <p30f6014.h> //dsPIC30F6014标准头文件
_FOSC(0x0ffe5); //4倍频晶振,Failsafe 时钟关闭
_FWDT(WDT_OFF); //关闭看门狗定时器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉电复位禁止,MCLR复位使能。
_FGS(CODE_PROT_OFF); //代码保护禁止
unsigned long int i = 0;
#define uch unsigned char //给unsigned char起别名 uch
# define DQ PORTFbits.RF6 //定义18B20数据端口
# define DQ_DIR TRISFbits.TRISF6 //定义18B20D口方向寄存器
# define DQ_HIGH() DQ_DIR =1 //设置数据口为输入
# define DQ_LOW() DQ = 0; DQ_DIR = 0 //设置数据口为输出
#define rs LATBbits.LATB4 //定义LCD控制位(注意这里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5
#define e LATBbits.LATB6
unsigned char __attribute__((address(0x900))) TLV; //采集到的温度高8位
unsigned char __attribute__((address(0x902))) THV; //采集到的温度低8位
unsigned char __attribute__((address(0x904))) TZ; //转换后的温度值整数部分
unsigned char __attribute__((address(0x906))) TX; //转换后的温度值小数部分
unsigned int __attribute__((address(0x908))) wd; //转换后的温度值BCD码形式
unsigned char __attribute__((address(0x9a0))) loop; //LCD显示次数计数器
//**********************CAN总线初始化*************************
void initcan()
{
C1CTRLbits.REQOP = 0x4; //请求进入配置模式
while (C1CTRLbits.OPMODE!=0x4){} //确认进入配置模式
C1TX0CON = 0x0003; //发送0邮箱配置
C1TX0SID = 0x0020; //发送0标准标识符,11位
C1TX0DLC = 0x01c0; //发送0数据长度,8字节
C1RX0CON = 0x0000; //接收0邮箱配置
C1RX0DLC = 0x0008; //接收0数据长度,8字节
C1RXF0SID = 0x0020; //接收滤波器0标准标识符,11位
C1RXM0SID = 0xffff; //接收屏蔽0标准标识符
C1CFG1bits.SJW=0; //SJW=1 x TQ
C1CFG1bits.BRP = 9; //125K
C1CFG2 = 0x03Ac; //SEG2PH=5;SEG1PH=6;PRSEG=4
C1CTRLbits.REQOP = 0x0; //请求进入正常模式
while (C1CTRLbits.OPMODE!=0x0){} //确认进入正常模式
return;
}
//**********************延时函数**************************
//延时函数(延时时间为(2+x)us)
void delay( char x)
{
unsigned char i;
for(i=0;i<x;i++);
}
//********************系统初始化函数**********************
void init()
{
TRISF=0X0000; //先设置18B20口方向为输出
TRISB=0X0000; //设置B口方向为输出
TRISD=0X0000; //设置D口方向为输出
IFS0bits.T1IF=0; //先清除定时器中断标志位
PR1=0XFFFF; //周期定最大
T1CON=0X0020; //分频比为1:64
INTCON1=0x0000;
INTCON2=0x0000; //关闭所有中断
}
//******************复位DS18B20函数*****************************
//主控制器(dsPIC30F6014A)先拉低总线480us,然后释放总线回到高电平
//18B20检测到上升沿后先等待15-60us,然后拉低总线做为复位的应答信号
//主控制器释放总线后到复位结束时间应为480US
reset(void)
{
char presence=1;
while(presence)
{
DQ_LOW() ; //主机拉至低电平
delay(100);
delay(100);
delay(100);
delay(100);
delay(78); //以上5条共延时480us
DQ_HIGH(); //释放总线等电阻拉高总线,并保持15~60us
delay(38); //延时40us
if(DQ==1) presence=1; //没有接收到应答信号,继续复位
else presence=0; //接收到应答信号
delay(100);
delay(100);
delay(100);
delay(100);
delay(38); //以上5条共延时440us
}
}
//****************写18b20写字节函数*****************************
//主控制器写数据1:先把总线拉低,然后在15us内释放总线
//主控制器写数据0:把总线拉低至少60us
//写一位数据至少需要60us
//两位数据之间至少延时1us
void write_byte(uch val)
{
uch i;
uch temp;
for(i=8;i>0;i--)
{
temp=val&0x01; //最低位移出
DQ_LOW();
delay(3); //保持拉低5us
if(temp==1) DQ_HIGH(); //如果写1,拉高电平
delay(58); //延时60us
DQ_HIGH();
delay(1); //在两位之间插入3us延时
val=val>>1; //右移一位
}
}
//****************18b20读字节函数********************************
//主控制器把总线拉低至少1US,然后释放
//主控制器读数据1:18B20保持总线状态不变
//主控制器读数据0:18B20检测到总线拉低后继续拉低总线至少60ms
//主控制器在拉低总线后的15us读取总线上的状态
//读取1位数据至少需要60us
uch read_byte(void)
{
uch i;
uch value=0; //读出温度
for(i=8;i>0;i--)
{
value>>=1;
DQ_LOW();
delay(1); //保持总线拉低3us
DQ_HIGH(); //拉至高电平
delay(5); //释放总线后保持7us再读取数据
if(DQ) value|=0x80;
delay(48); //延时50us,保证每1位的60us延时
}
return(value);
}
//*****************启动温度转换函数***************************
void get_temp()
{
int i;
DQ_HIGH();
reset(); //复位等待从机应答
write_byte(0XCC); //忽略ROM匹配
write_byte(0X44); //发送温度转化命令
for(i=0;i<8;i++)
{
delay(98); //确保温度转换完成所需要的时间
}
reset(); //再次复位,等待从机应答
write_byte(0XCC); //忽略ROM匹配
write_byte(0XBE); //发送读温度命令
TLV=read_byte(); //读出温度低8
THV=read_byte(); //读出温度高8位
DQ_HIGH(); //释放总线
TZ=(TLV>>4)|(THV<<4)&0X3f; //温度整数部分
TX=TLV<<4; //温度小数部分
}
//************************主函数********************************
int main(void)
{
init(); //调用系统初始化函数
initcan();
LATDbits.LATD0=1;
LATDbits.LATD1=0;
while(1)
{
TMR1=0XC2F6; //定时器初值
T1CONbits.TON=1; //启动定时器
while(!IFS0bits.T1IF); //等待0.1s定时到
IFS0bits.T1IF=0;
get_temp(); //调用温度转换函数
C1TX0B1 = TZ;
C1TX0B2 = TX;
C1TX0B3 = 0x5A5A; //B3跟B4四字节数据无效,也可做效验用
C1TX0B4 = 0xa5a5;
C1TX0CONbits.TXREQ = 1; //启动发送
while (C1TX0CONbits.TXREQ==1){} //等待发送完成
for (i=0;i<2;i++){}
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1