📄 main.c
字号:
#include <P8XC5X2.H>
#include <intrins.H>
#include "sja_bcanconf.h"
#include "X5045.h"
sbit io=P2^6;
/*CAN通信定义*/
volatile unsigned char bdata flag_init; //保存中断寄存器值
sbit rcv_flag=flag_init^0; //接收中断标志
sbit err_flag=flag_init^2; //错误中断标志
unsigned char SendBuf[6]; //CAN发送缓冲区
unsigned char SampleHVal[8],SampleLVal[8]; //模拟量采集结果
#define BaseID 0
#define RTR 0
#define DLC 4
#define V_T1s 255 //1秒
#define V_T1m 20
#define V_T50ms 10 //100ms
#define V_TH0 0xEA /*10ms ,!notice: crystal 24MHz */
#define V_TL0 0x00
#define TERMINAL 0x00 //主机命令CAN通信标识兼功能码
volatile unsigned char CanID; //当前CAN节点的标识
void LedTest()
{
static char led=1;
led=!led;
io=led;
}
void InitWtd()
{
wren_dog(); //看门狗写使能
wrsr_dog(0x03); //看门狗周期1.4秒
wrdi_dog(); //看门狗写禁止
}
void FeedDog()
{
rest_dog();
}
void delayUs()
{
_nop_();
}
void delayMs(unsigned char a)
{
unsigned char i, j;
for(i = a; i > 0; i--)
for(j = 100; j > 0; j--);
}
/**//*****************************DS18B20*******************************/
sbit ds = P1^0;
//初始化DS18B20
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
void dsInit()
{
//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us
unsigned char i;
ds = 0;
i = 100; //拉低约800us, 符合协议要求的480us以上
while(i>0) i--;
ds = 1; //产生一个上升沿, 进入等待应答状态
i = 5;
while(i>0) i--;
}
void dsWait()
{
unsigned char i;
while(ds)FeedDog();
while(~ds)FeedDog(); //检测到应答脉冲
//LedTest();
i = 4;
while(i > 0) i--;
}
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit readBit()
{
unsigned char i;
bit b;
ds = 0;
i++; //延时约8us, 符合协议要求至少保持1us
ds = 1;
i++; i++; //延时约16us, 符合协议要求的至少延时15us以上
b = ds;
i = 10;
while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求
return b;
}
//读取一字节数据, 通过调用readBit()来实现
unsigned char readByte()
{
unsigned char i;
unsigned char j, dat;
dat = 0;
for(i=0; i<8; i++)
{
j = readBit();
//最先读出的是最低位数据
dat = (j << 7) | (dat >> 1);
}
return dat;
}
//向DS18B20写入一字节数据
void writeByte(unsigned char dat)
{
unsigned char i;
unsigned char j;
bit b;
for(j = 0; j < 8; j++)
{
b = dat & 0x01;
dat >>= 1;
//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1
if(b)
{
ds = 0;
i++; i++; i++; //拉低约16us, 符号要求15~60us内
ds = 1;
i = 10; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求
}
else //写"0", 将DQ拉低60us~120us
{
ds = 0;
i = 10; while(i>0) i--; //拉低约64us, 符号要求
ds = 1;
i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了
}
}
}
//向DS18B20发送温度转换命令
void sendChangeCmd()
{
dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化
dsWait(); //等待DS18B20应答
delayMs(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
writeByte(0x44); //写入温度转换命令字 Convert T
}
//向DS18B20发送读取数据命令
void sendReadCmd()
{
dsInit();
dsWait();
delayMs(1);
writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
writeByte(0xbe); //写入读取数据令字 Read Scratchpad
}
//获取当前温度值
void getTmpValue()
{
sendReadCmd();
//连续读取两个字节数据
SampleLVal[0] = readByte();
SampleHVal[0] = readByte();
//if(SampleHVal[0]==0xFF)LedTest();
}
/**//*****************************DS18B20*******************************/
void InitCPU()
{
EX0 =1;
PX0 =1;
}
void CheckCan()
{
if(rcv_flag) //if there is receive charerrupt
{
}
if(err_flag)
{
EA=0;
err_flag=0; //错误标志位清零
Config_SJA(); //初始化SJA
EA=1;
}
}
void SendByCan()
{
SendBuf[0]=TERMINAL; //主机标识
SendBuf[1]=0x00|DLC; //标识低3位和RTR以及请求数据位数
SendBuf[2]=CanID; //本地CAN标识
SendBuf[3]=0; //第i路遥测值
SendBuf[4]=SampleLVal[0]; //遥测低字节值
SendBuf[5]=SampleHVal[0]; //遥测高字节值
BCAN_DATA_WRITE(SendBuf);
BCAN_CMD_PRG(TR_CMD);
}
void InitCanID()
{
//读入P2口状态,其中0~3为跳线设置
CanID=~P2;
CanID&=0x0f;
CanID|=0x80;
}
void main()
{
InitCanID(); //计算当前节点的CAN标识
Config_SJA(); //CAN初始化,SJA1000配置
InitCPU(); //CPU初始化
P3_4=0;
P1=0;
InitWtd(); //看门狗电路初始化
sendChangeCmd();
while(1)
{
CheckCan();
delayMs(255); //温度转换时间需要750ms以上
FeedDog();
delayMs(255);
delayMs(255);
FeedDog();
delayMs(255);
delayMs(255);
FeedDog();
delayMs(255);
delayMs(255);
getTmpValue();
SendByCan();
//LedTest();
sendChangeCmd();
FeedDog();
}
}
void SJA_INTR() interrupt 0 using 1
{
SJA_BCANAdr=REG_INTERRUPT; //指针指向中断寄存器
flag_init=*SJA_BCANAdr; //保持中断寄存器值
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -