📄 main11.c
字号:
#include <absacc.h>
#include <P89C58_PLUS.H>
#include "SJA1000.h"
#define MAX_AD_RECV_LEN 24
#define SLOT_ADDR 0xB000
#define SLOT_ADDR_COM 0x02 // 定义基址
#define CAN_FLAG_NONE 0x00
#define CAN_FLAG_START 0x01
#define CAN_FLAG_RUNNING 0x02
#define CAN_FLAG_END 0x03
#define STA_IDLE 0
#define STA_RECEIVING 1
#define STA_SENDING 2
sbit CAN0_RST = P3^4;
sbit CAN1_RST = P1^0;
sbit CS_LED = P1^3;
sbit AD_CLK = P1^4;
sbit AD_OUT = P1^5;
sbit AD_IN = P1^6;
sbit AD_EOC = P3^3;
sbit CS_AD = P1^7;
sbit TEST = P3^3;
unsigned char idata m_ad_buff[MAX_AD_RECV_LEN]; //高128位RAM7F-ff 指针方式
unsigned int idata m_ad_tmp[5][11];
unsigned char m_times;
unsigned char bdata m_led_cond;//可位寻址的内存空间
sbit b_led1=m_led_cond^0;
sbit b_led2=m_led_cond^1;
sbit b_led3=m_led_cond^2;
sbit b_led4=m_led_cond^3;
sbit b_led5=m_led_cond^4;
sbit b_led6=m_led_cond^5;
sbit b_led7=m_led_cond^6;
sbit b_led8=m_led_cond^7;
unsigned char xdata *m_pByte;
unsigned int m_last_time;
unsigned int m_out_time;
unsigned char m_addr;
unsigned char m_chn_no;
// ...CAN 缓冲区....//
unsigned char m_CanSend[10];
unsigned char m_CanRecv[10];
bit m_bAuto;
unsigned char m_can_msg_len;
unsigned char m_can_recvs;
unsigned char idata m_buffull;
void P89C58_init();
void SJA1000_init();
bit SJA1000_Send();
void TLC2543C_init();
unsigned char GetCANAddr();
unsigned int GetCRC(unsigned char num,unsigned char *pData);
extern void _nop_ (void);
void delay(unsigned int num)
{
unsigned int i;
for (i = 0; i < num; i ++) {
_nop_();
}
}
//AD采样状态显示子程序//
void LightLed()
{
unsigned char i;
unsigned char tmp;
unsigned char led;
unsigned int m_ad_result;
led = 0;
for(i=0;i<8;i++)
{
m_ad_result = m_ad_buff[2*i]<<8;
m_ad_result += m_ad_buff[2*i+1];
tmp = m_led_cond&(0x01<<i);
if(tmp&&(m_ad_result < 630))
{
led = led & (~(0x01<<i));
}
else led = led | (0x01<<i);
}
EA = 0;
P0 = led;
CS_LED = 1;
CS_LED = 0;
EA = 1;
}
// ..得到CRC校验数据//
unsigned int GetCRC(unsigned char num,unsigned char *pData)
{
unsigned char i,j;
unsigned int m_CRC;
m_CRC = 0xffff;
for( i = 0; i < num; i ++)
{
m_CRC = m_CRC^(*(pData + i));
for( j = 0; j < 8; j++ )
{
if(m_CRC & 0x01)
{
m_CRC = m_CRC >> 1;
m_CRC=m_CRC ^ 0xa001;
}
else
{
m_CRC = m_CRC >> 1;
}
}
}
return m_CRC;
}
/***************************************************************************************************************************************
..........................................P89C58.............................
**************************************************************************************************************************************/
void P89C58_init()
{
TMOD = 0x21; //Mode 2: 自动复位
RCAP2H = 0xFF;
RCAP2L = 0xB2;
CS_LED = 0; //disable 573
TH0 = 0xF8; //...1mS 中断
TL0 = 0x30;
// ...开中断//
IE = 0;
ET0 = 1; //T0中断使能
EX0 = 1; // 为 SJA1000 INT使能 INT0
EX1 = 0; //关闭 AD INT 的INT1
ES = 0; //关闭串口中断.
// ...启动定时器 2
TR0 = 1;
}
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
* Function:P89C58_ISR_Timer0()
* Description:
* Timer0 中断服务子程序
*/
void P89C58_ISR_Timer0() interrupt 1 using 2
{
m_last_time = m_last_time ++;
if(m_last_time > 3000) m_last_time = 3000;
TH0 = 0xF8; //...1mS interrupt
TL0 = 0x30;
TR0 = 1;
}
/***************************************************************************************************************************************
..........................................SJA1000.............................
**************************************************************************************************************************************/
void SJA1000_init()
{
int j;
CAN0_RST = 0;/*硬件复位SJA1000 ,拉低RST引脚*/
for(j = 0; j < 1000; j ++)
{
_nop_(); /*持续一段时间*/
}
CAN0_RST = 1;/*释放,硬件复位结束*/
SJA_REG_CR = 0x01; // 进入复位模式
SJA_REG_ACR = m_addr;/*接收码为本程采集单元地址*/
SJA_REG_AMR = 0x03; /* 0000 00XX 接收屏蔽码,1、2不相关*/
SJA_REG_BTR0 = 0x00;/*总线定时器0缺省*/
SJA_REG_BTR1 = 0x14;/*总线定时器1,24Mhz晶振,9.6kb/s*/
SJA_REG_OCR = 0xAA;/*输出控制寄存器,正常输出模式,TX0正逻辑、下拉输出驱动*/
SJA_REG_CDR = 0x48;/*can模式为basicCAN模式,CLKOUT关闭,允许外接发送接收电路*/
// 进入工作模式
SJA_REG_CR = 0x1A; /*允许溢出、出错、接收中断,但不发送数据 */
}
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
* Function:
* Description:
* CAN 中断服务子程序
*/
void SJA1000_ISR_0() interrupt 0 using 1
{
unsigned char i;
unsigned char num;
unsigned char dlc;
unsigned char status;
unsigned char iir;
iir = SJA_REG_IR;
status = SJA_REG_SR;
if (iir & 0x01) {//接收中断
m_CanRecv[0] = SJA_REG_RxBuf0;
m_CanRecv[1] = SJA_REG_RxBuf1;
dlc = m_CanRecv[1] & 0x0F;
for ( i = 0; i < dlc; i ++){
m_pByte = SJA_REG + 0x16 + i; // 接收数据送入缓冲区
num = *m_pByte;
m_CanRecv[i + 2] = num;
}
m_can_msg_len=dlc-1;
m_buffull = 0x55;
SJA_REG_CMD = 0x04; /*命令寄存器 RRB=1 释放SJA1000接收缓存*/
}
if (iir & 0x08) {//数据溢出中断
SJA_REG_CMD = 0x08; // CDO=1 清除数据溢出
}
}
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
* Function:SJA1000_Send()
* Description:
* SJA1000 发送数据
*/
bit SJA1000_Send()
{
unsigned char i;
unsigned char num;
unsigned char status;
status = SJA_REG_SR;
if (status & 0x04 == 0) return 0;/*状态,判断上次发送完成且发送缓存已释放*/
if (status & 0x08 == 0) return 0;
for ( i = 0; i < 200; i ++) {
_nop_();
}
num = m_CanSend[1] & 0x0F;
num = num + 2;
for ( i = 0; i < num; i ++)//写入发送缓存
{
m_pByte = SJA_REG + 0x0A + i; // 0x0A: 发送缓存区偏移地址
*m_pByte = m_CanSend[i];
}
SJA_REG_CMD = 0x01; // TR=1 置发送请求
return 1;
}
/***************************************************************************************************************************************
..........................................AD Converter(TLC2543C).............................
ADDRESS BITS L1 L0 LSBF BIP
D7 D6 D5 D4 D3 D2 D1 D0
(MSB) (LSB)
**************************************************************************************************************************************/
//AD 初始化子程序//
void TLC2543C_init()
{
unsigned char i;
AD_CLK = 0;
CS_AD = 0;
for (i = 0; i < 22; i ++) m_ad_buff[i] = 0;
delay(5);
}
//AD数据处理子程序//
void TLC2543C_filter()
{
unsigned char i;
unsigned char j;
unsigned int max;
unsigned int min;
unsigned int sum;
for (i=0;i<11;i++)
{
max = m_ad_tmp[0][i];
min = m_ad_tmp[0][i];
for(j=1;j<5;j++) //得到最大值和最小值
{
if(m_ad_tmp[j][i] > max) max = m_ad_tmp[j][i];
else if(m_ad_tmp[j][i] < min) min = m_ad_tmp[j][i];
}
sum = 0; //计算5个值的总和
for(j=0;j<5;j++)
{
sum += m_ad_tmp[j][i];
}
sum = sum - max; //减去最大值和最小值
sum = sum - min;
sum = sum / 3;
m_ad_buff[2*i] = sum >> 8; //得到处理结果
m_ad_buff[2*i+1] = sum;
}
}
//AD采样子程序//
unsigned int TLC2543C_ad(unsigned char channel)
{
unsigned char chn;
unsigned char i;
unsigned int val;
chn = channel<<4; /*0xB0----(Vref+ - Vref-)/2 0xC0---Vref- 0xD0---Vref+*/
val = 0;//差动
AD_CLK = 0;
CS_AD = 0;
delay(10);
for (i = 0; i < 12; i ++) {
if (chn & 0x80) AD_IN = 1;
else AD_IN = 0;
chn <<= 1;
delay(10);
AD_CLK = 1;
val = val << 1;
if (AD_OUT) val ++;
delay(10);
AD_CLK = 0;
}
delay(10);
CS_AD = 1;
return val;
}
//CAN 总线地址//
unsigned char GetCANAddr() {
unsigned char tmp_addr;
m_pByte = SLOT_ADDR;
tmp_addr = *m_pByte;
tmp_addr = tmp_addr & 0x0F;
tmp_addr = tmp_addr - SLOT_ADDR_COM;
tmp_addr = tmp_addr*4;
return tmp_addr;
}
// ...CAN 总线数据传输//
void UploadData()
{
m_CanSend[0] = m_addr;
m_CanSend[1] = 0x08;
m_CanSend[2] = CAN_FLAG_START;
m_CanSend[3] = m_ad_buff[0]; //chn0
m_CanSend[4] = m_ad_buff[1];
m_CanSend[5] = m_ad_buff[2]; //chn1
m_CanSend[6] = m_ad_buff[3];
m_CanSend[7] = m_ad_buff[4]; //chn2
m_CanSend[8] = m_ad_buff[5];
m_CanSend[9] = m_ad_buff[6]; //chn3
while(!SJA1000_Send());
m_CanSend[0] = m_addr;
m_CanSend[1] = 0x08;
m_CanSend[2] = CAN_FLAG_RUNNING;
m_CanSend[3] = m_ad_buff[7];
m_CanSend[4] = m_ad_buff[8]; //chn4
m_CanSend[5] = m_ad_buff[9];
m_CanSend[6] = m_ad_buff[10]; //chn5
m_CanSend[7] = m_ad_buff[11];
m_CanSend[8] = m_ad_buff[12]; //chn6
m_CanSend[9] = m_ad_buff[13];
while(!SJA1000_Send());
m_CanSend[0] = m_addr;
m_CanSend[1] = 0x08;
m_CanSend[2] = CAN_FLAG_RUNNING;
m_CanSend[3] = m_ad_buff[14]; //chn7//
m_CanSend[4] = m_ad_buff[15];
m_CanSend[5] = m_ad_buff[16]; //chn8//
m_CanSend[6] = m_ad_buff[17];
m_CanSend[7] = m_ad_buff[18]; //chn9//
m_CanSend[8] = m_ad_buff[19];
m_CanSend[9] = m_ad_buff[20]; //chn10//
while(!SJA1000_Send());
m_CanSend[0] = m_addr;
m_CanSend[1] = 0x04;
m_CanSend[2] = CAN_FLAG_END;;
m_CanSend[3] = m_ad_buff[21];
m_CanSend[4] = m_ad_buff[22];
m_CanSend[5] = m_ad_buff[23]; //sum
while(!SJA1000_Send());
}
//...串口传输协议....//
void STProtocol()
{
unsigned char fun;
unsigned int timeout;
bit bRet=1;
fun = m_CanRecv[3];
if(m_buffull!=0x55) return;
m_buffull=0;
if (fun == 0x04 && m_can_msg_len == 4) //功能码:用来设置数据上传的时间间隔
{// 设置检测延迟时间
timeout = m_CanRecv[5];
timeout = timeout << 8;
timeout = timeout + m_CanRecv[4];
m_out_time = timeout;
m_led_cond = m_CanRecv[6];
}
else if (fun == 0x06 && m_can_msg_len == 1) //0x06功能码:使数据采集板复位
{// 复位
while(1) {;} //等待看门狗
}
else if (fun == 0x07 && m_can_msg_len == 1) //0x07功能码:用来停止数据上传。
{// 是否准备发送实时命令
m_bAuto = 0;
}
else if (fun == 0x08 && m_can_msg_len == 1) //0x08功能码:用来启动数据上传
{// 开始发送实时命令
m_bAuto = 1;
}
else
{
bRet = 0;
}
if (bRet)
{
m_CanSend[0] = m_addr;
m_CanSend[1] = 0x03;
m_CanSend[2] = CAN_FLAG_END;
m_CanSend[3] = fun;
m_CanSend[4] = 0;
while(!SJA1000_Send());
}
}
void main(void)
{
unsigned char i;
unsigned int value;
EA = 0;
m_addr = GetCANAddr();
P89C58_init();
SJA1000_init();
TLC2543C_init();
m_out_time = 200;
m_can_recvs = 0;
m_can_msg_len=0;
m_led_cond = 0x00; //电流环断线时指示灯灭
m_bAuto = 0;
EA = 1;
while(1)
{
kickdog;//喂狗
STProtocol();
m_times ++;
if(m_times > 4) m_times = 0;
for(i=0;i<11;i++) //得到AD采样值,大约22MS
{
if(i==10) m_ad_tmp[m_times][i] = TLC2543C_ad(0);
else m_ad_tmp[m_times][i] = TLC2543C_ad(i+1);
}
TLC2543C_filter(); //AD数据处理
LightLed(); //显示AD采样对应在显示面板上的状态
if (!m_bAuto) continue; //不更新数据
if (m_last_time < m_out_time) continue; //时间没有到,数据暂时不需更新
m_last_time = 0;
m_addr = GetCANAddr();
value = GetCRC(22, m_ad_buff); //CRC校验
m_ad_buff[22]=value;
m_ad_buff[23]=value>>8;
UploadData(); //更新AD数据
}
}// end main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -