📄 ussensor.c
字号:
break;
}
case (AUTO_MEASURE + READ_BACK_DATA):
{
// 自动测量模式下被动数据返回处理
g_bTxdFinish = TRUE; // 因无需数据返回,所以建立数据返回结束标志
g_ucWorkStat = WAIT_FINISH; // 转换到等待数据返回结束状态
break;
}
case (SINGLE_MEASURE + NOPROC_BACK):
{
// 返回指定次数的数据,不作处理
backMeaData(NOPROC_BACK);
break;
}
case (SINGLE_MEASURE + MID_BACK):
{
// 去除最大最小值后返回
if(g_ucModePara<3)
{
g_ucWorkMode = SINGLE_MEASURE + NOPROC_BACK; // 如果测量次数小于 3 ,则按照不处理模式返回
}
else
{
sortLastData(g_ucModePara);
backMeaData(MID_BACK);
}
break;
}
case (SINGLE_MEASURE + MEAN_BACK):
{
// 返回平均值
backMeaData(MEAN_BACK);
break;
}
case (SINGLE_MEASURE + MID_MEAN_BACK):
{
if(g_ucModePara < 4)
{
g_ucWorkMode = SINGLE_MEASURE + MID_BACK; // 如果测量次数小于 4 ,则按照去除最大最小值模式返回
}
else
{
sortLastData(g_ucModePara);
backMeaData(MID_MEAN_BACK);
}
break;
}
default:break;
}
break;
}
case WAIT_FINISH:
{
if(g_bTxdFinish) // 等待数据返回结束
{
g_bTxdFinish = FALSE;
g_ucWorkStat = WAIT_START; // 开始新一轮测量过程
}
break;
}
default:break;
} // 工作状态处理部分结束
}
}
/********** 函数 **************/
/********************************************/
/*名称: init_hardware */
/*用途: 硬件初始化函数 */
/*说明: 初始化所有相关的硬件状态 */
/********************************************/
void init_hardware(void)
{
/* 初始化系统时钟 */
CLK_DIV = CLKDIV1_C;
/* 初始化I/O口*/
P1M0 = P1M0_C;
P1M1 = P1M1_C;
P3M0 = P3M0_C;
P3M1 = P3M1_C;
g_bSend_Ctrl = SEND_INVALID; // 超声波输出驱动无效
g_bUltraSonicDrvValid = FALSE;
g_bCut_Off = CUT_OFF_INVALID; // 回波抑制无效
g_b852Inhibit = DIS852OUT; // 禁止 852 输出
/* 初始化定时器 */
TMOD = T0MODE1|T1MODE2; // Timer0工作在模式1 ,16位定时,Timer1 工作在模式 2 ,8位重加载,作为波特率发生器;
AUXR = AUXR&CLR_T0X12_C; // Timer0 工作在12分频
TCON = INT1_DOWN; // 定义中断1 的触发方式
TH0 = TIME1msH_C;
TL0 = TIME1msH_C;
TR0 = TRUE;
/* 初始化中断 */
IE = EnT0_C|EnINT1_C; // 允许 Timer0、INT1、PCA 中断
IPH = NOIP_C; // 此处不设优先级,有各功能模块自身设定
IP = NOIP_C;
/* 看门狗初始化程序 */
WDT_CONTR = Watchdog_C; // 设置 WDT 分频
/* 初始化UART */
init_SIO(B_19200);
IE = IE|EnUART_C; // 允许 UART 中断
/* 初始化PCA */
CMOD = FOSCdiv2_C|EnCF_C; // PCA 时钟源为 Fosc/2 , 允许 count 溢出中断 CF。休眠时 PCA 工作
CCAPM1 = EnCMP_C|EnMAT_C|EnCCFI_C; // PCA 的模块 1 用于控制脉冲发送和增益变化,计时器模式,比较、匹配中断
IE = IE|EnPCALVD_C; // 初始化PCA中断
CL = 0;
CH = 0;
CCON = CCON&STOPPCA_C; // 上电时 PCA 停止待命
}
/********************************************/
/*名称: init_var */
/*用途: 变量初始化 */
/*说明: 初始化全局变量 */
/********************************************/
void init_var(void)
{
// WDT参数初始化
g_b1msFlag=FALSE;
gc_uiWdtCnt=WDTTIME_C;
/* 状态初始化 */
g_ucWorkStat = WAIT_START;
g_b1msFlag = FALSE;
gc_uc10msCnt = 10;
g_ucWorkDispStat = NORMAL;
gc_uiWorkDispTimeCnt = ga_uiWorkDispTime[g_ucWorkDispStat];
gc_ucWorkDispNumCnt = ga_ucWorkDispNum[g_ucWorkDispStat];
/* 初始化UART 部分变量 */
gi_ucSavePtr = 0;
gi_ucGetPtr = 0;
g_bNewData = FALSE;
g_bStartRcv = FALSE;
g_bTxdFinish = FALSE;
ga_ucTxdBuf[0] = 0x55; // 因为发送缓冲区暂不作他用,所以先存好,以减少代码
ga_ucTxdBuf[1] = 0xAA; // 帧头,
ga_ucTxdBuf[3] = MY_ADDR; // 自己的地址作为发送方地址送出
/* 初始化超声波检测、计算部分变量 */
g_ucWorkMode = STOP_MEASURE;
g_ucModePara = 0;
gc_ucMeaPeriodCnt = 0;
gc_ucMeaTimesCnt = 0;
gc_ucGapAtSingleMea = 0;
gi_ucDataSavePtr = 0;
g_bGainCtrl = FALSE;
}
/********************************************/
/*名称: feed_watchdog */
/*用途: 喂狗程序 */
/*说明: 请参照STC12C5410的喂狗方法说明 */
/********************************************/
void feed_watchdog(void)
{
WDT_CONTR = CLRWDT_C;
}
/********************************************/
/* 名称:init_SIO */
/* 用途:初始化串口, */
/* 参数: 波特率 , 模式固定为:1 */
/* 1 START 8 DATA 1 STOP */
/********************************************/
void init_SIO(unsigned char baud)
{
// 波特率表
unsigned char code TH_Baud[5]={B4800_C,B9600_C,B19200_C,B38400_C,B57600_C};
AUXR = AUXR|SET_T1X12_C;
TH1 = TH_Baud[baud];
TL1 = TH_Baud[baud];
TR1 = TRUE;
SCON = UART_MODE1_C|EN_RCV_C; // 8 位模式( MODE 1)
}
/********************************************/
/*名称: dataFrame_OK */
/*用途: 检测接收缓冲区数据, */
/*说明: 如果收到正确的数据帧则返回真 */
/********************************************/
bit dataFrame_OK(void)
{
unsigned char i,j,k;
bit flag;
flag = FALSE;
while(gi_ucGetPtr != gi_ucSavePtr)
{
if(g_bStartRcv == FALSE)
{
/* 检测帧头 0x55 0xAA MY_ADDR */
k = 0;
i = (gi_ucGetPtr - 5)&(MaxRcvByte_C-1);
if(ga_ucRcvBuf[i]==0x55)
{
k++;
}
i = (gi_ucGetPtr - 4)&(MaxRcvByte_C-1);
if(ga_ucRcvBuf[i]==0xAA)
{
k++;
}
i = (gi_ucGetPtr - 3)&(MaxRcvByte_C-1);
if(ga_ucRcvBuf[i]==MY_ADDR)
{
k++;
}
if(k == 3)
{
//帧头正确,启动数据区接收
g_bStartRcv=TRUE;
i=(gi_ucGetPtr-1)&(MaxRcvByte_C-1);
gc_ucDataLen = ga_ucRcvBuf[i];
gi_ucStartPtr = gi_ucGetPtr;
gi_ucEndPtr= (gi_ucGetPtr + gc_ucDataLen)&(MaxRcvByte_C-1);
}
}
else
{
//开始接收数据处理
if(gi_ucGetPtr==gi_ucEndPtr)
{
/* 数据帧接收完 */
g_bStartRcv=FALSE;
j=gi_ucStartPtr;
k= 0;
for(i=0;i<gc_ucDataLen;i++)
{
// 计算CS
k +=ga_ucRcvBuf[j];
j=(j+1)&(MaxRcvByte_C-1);
}
// 取校验和
k = ~k;
if(k==ga_ucRcvBuf[j])
{
flag = TRUE; // 数据校验正确
}
}
}
gi_ucGetPtr=(gi_ucGetPtr+1)&(MaxRcvByte_C-1);
}
return (flag);
}
/********************************************/
/*名称: do_Command */
/*用途: 根据收到的数据帧命令做相应处理 */
/********************************************/
void do_Command(void)
{
unsigned char ucCommand,i,j,k,sum,n;
union
{
unsigned int all;
unsigned char b[2];
}uitemp;
unsigned char idata *ucI_Ptr;
unsigned char xdata *ucX_Ptr;
unsigned char code *ucC_Ptr;
ucCommand = ga_ucRcvBuf[gi_ucStartPtr]; // 取出数据帧中的命令
switch (ucCommand)
{
case READ_MEMORY:
{
// 读内存数据处理
i = (gi_ucStartPtr + 1)&(MaxRcvByte_C-1);
uitemp.b[1] = ga_ucRcvBuf[i]; // 取读数据地址, 注意 C51 中的多字节数据与PC中相反
i =(i+1)&(MaxRcvByte_C-1);
uitemp.b[0] = ga_ucRcvBuf[i];
i =(i+1)&(MaxRcvByte_C-1);
n = ga_ucRcvBuf[i]; // 取读数据长度
if(n>(MaxTxdByte_C - 10))
{
n = (MaxTxdByte_C - 10); // 受发送缓冲区限制,减 10 个字节对应:
// 帧头2 设备地址2 长度1 命令1 数据地址2 字节数1 .... 校验和1
}
i = (gi_ucStartPtr-2)&(MaxRcvByte_C-1); // 取发送方地址
ga_ucTxdBuf[2] = ga_ucRcvBuf[i]; // 作为接收方地址发送
ga_ucTxdBuf[4] = n + 4; // 帧长
ga_ucTxdBuf[5] = READ_MEMORY; // 返回命令
ga_ucTxdBuf[6] = uitemp.b[1]; // 将要读数据的地址和长度返回
ga_ucTxdBuf[7] = uitemp.b[0];
ga_ucTxdBuf[8] = n;
sum = ga_ucTxdBuf[5]+ga_ucTxdBuf[6]+ga_ucTxdBuf[7]+ga_ucTxdBuf[8];
i = 9; // 数据区起始指针
if(uitemp.b[0] == 0x00)
{
// 如果高地址为 0 ,则读IDATA内容
ucI_Ptr = uitemp.b[1];
for(j=0;j<n;j++)
{
ga_ucTxdBuf[i] = *ucI_Ptr;
sum += ga_ucTxdBuf[i];
i++;
ucI_Ptr++;
}
}
if(uitemp.b[0] == 0x01) // 注:此段程序对2052无效,暂时保留
{
// 如果高地址为“0x01”,则读XDATA内容
ucX_Ptr = uitemp.b[1]; // 因为只有256字节的XDATA,所以只取低字节。
for(j=0;j<n;j++)
{
ga_ucTxdBuf[i] = *ucX_Ptr;
sum += ga_ucTxdBuf[i];
i++;
ucX_Ptr++;
}
}
// 读 SFR 暂不支持,读者可以思考一下如何添加?
if(uitemp.b[0] >= 0x80)
{
// 如果高地址大于“0x80”,则读code(程序区)内容
ucC_Ptr = uitemp.all - 0x8000;
for(j=0;j<n;j++)
{
ga_ucTxdBuf[i] = *ucC_Ptr; // 注意,此功能将使你的程序泄密 :P
sum += ga_ucTxdBuf[i];
i++;
ucC_Ptr++;
}
}
ga_ucTxdBuf[i] = ~sum; // 校验和
gc_ucTxdCnt = i+1; // 发送字节计数
gi_ucTxdPtr = 0; // 发送指针
SBUF = ga_ucTxdBuf[0]; // 启动发送
break;
}
case WRITE_MEMORY:
{
// 写内存数据处理
i = (gi_ucStartPtr + 1)&(MaxRcvByte_C-1);
uitemp.b[1] = ga_ucRcvBuf[i]; // 取读数据地址
i =(i+1)&(MaxRcvByte_C-1);
uitemp.b[0] = ga_ucRcvBuf[i];
i =(i+1)&(MaxRcvByte_C-1);
n = ga_ucRcvBuf[i]; // 取读数据长度
i =(i+1)&(MaxRcvByte_C-1); // 数据区起始指针
j = 0; // 返回实际写的字节数
if(uitemp.b[0] == 0x00)
{
// 如果高地址为 0 ,则写IDATA内容
ucI_Ptr = uitemp.b[1];
for(j=0;j<n;j++)
{
*ucI_Ptr = ga_ucRcvBuf[i]; // 注意,此功能会导致程序崩溃 :(
i = (i+1)&(MaxRcvByte_C-1);
ucI_Ptr++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -