標題:
dsPIC30F6014 CAN總線發(fā)送功能+DS18B20溫度采集
[打印本頁]
作者:
xiaos
時間:
2015-4-2 23:18
標題:
dsPIC30F6014 CAN總線發(fā)送功能+DS18B20溫度采集
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; //發(fā)送0郵箱配置
C1TX0SID = 0x0020; //發(fā)送0標準標識符,11位
C1TX0DLC = 0x01c0; //發(fā)送0數據長度,8字節(jié)
C1RX0CON = 0x0000; //接收0郵箱配置
C1RX0DLC = 0x0008; //接收0數據長度,8字節(jié)
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++);
}
//********************系統(tǒng)初始化函數**********************
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; //沒有接收到應答信號,繼續(xù)復位
else presence=0; //接收到應答信號
delay(100);
delay(100);
delay(100);
delay(100);
delay(38); //以上5條共延時440us
}
}
//****************寫18b20寫字節(jié)函數*****************************
//主控制器寫數據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讀字節(jié)函數********************************
//主控制器把總線拉低至少1US,然后釋放
//主控制器讀數據1:18B20保持總線狀態(tài)不變
//主控制器讀數據0:18B20檢測到總線拉低后繼續(xù)拉低總線至少60ms
//主控制器在拉低總線后的15us讀取總線上的狀態(tài)
//讀取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); //發(fā)送溫度轉化命令
for(i=0;i<8;i++)
{
delay(98); //確保溫度轉換完成所需要的時間
}
reset(); //再次復位,等待從機應答
write_byte(0XCC); //忽略ROM匹配
write_byte(0XBE); //發(fā)送讀溫度命令
TLV=read_byte(); //讀出溫度低8
THV=read_byte(); //讀出溫度高8位
DQ_HIGH(); //釋放總線
TZ=(TLV>>4)|(THV<<4)&0X3f; //溫度整數部分
TX=TLV<<4; //溫度小數部分
}
//************************主函數********************************
int main(void)
{
init(); //調用系統(tǒng)初始化函數
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四字節(jié)數據無效,也可做效驗用
C1TX0B4 = 0xa5a5;
C1TX0CONbits.TXREQ = 1; //啟動發(fā)送
while (C1TX0CONbits.TXREQ==1){} //等待發(fā)送完成
for (i=0;i<2;i++){}
}
}
復制代碼
作者:
最閑的閑魚
時間:
2018-6-27 16:48
問一下,你這個CAN發(fā)送有沒有碰到過TXERR的情況?如果碰到了,怎么解決?謝謝
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1