📄 main.c
字号:
/******************************************
STC 单片机开发程序。V0_1_1
//在KEIL uVision3中,如有不清楚的函数封装,选中后点右键,选择“GO TO Ddfinition Of 'XXXXXX'“
//可以看到该函数的原形。
//create by changshengwuji
//email: netspider@163.com
//qq: 450353168
//2006.05.03
********************************************************************/
//5a 55 a2 51 read addr
//5a 10 a5 0f read integer t
//5a 10 a3 0d read tp
//5a 10 a6 10 shut
//5a 10 a7 11 open
//5a 10 a1 0b modify addr
#include "../inc/MCS_X51.H"
#include "../inc/hardmap.h"
#include "../inc/MCS_X51LIB.H"
#include "../inc/DS18B20.H"
#include "../inc/stc_flash.H"
#define EXT_11M 1 //外部11.0592MHz晶体
//#define EXT_1M 1 //外部输入时钟1Mhz
#define UART_ERR 0XEE
#define UART_SUC 0XA0
//------上位机命令---------------
#define SET_ADDR 0XA1 //设置本机地址
#define READ_ADDR 0XA2 //读取本机地址
#define READ_T 0XA3 //读取温湿度
#define HEAT 0XA4 //加热命令
#define READ_S 0XA5 //READ SHORT TEMPERATURE
#define SHUT 0XA6 //关
#define OPEN 0XA7 //开
#define TEST 0XA0 //TEST CODE
#define HEAD 0X5A //帧头
#define ADDR 0X10 //默认本机地址
#define ERR_ADDR 0XE1 //设置地址错误应答
#define ERR_VERI 0XE2 //上位机发送的数据校验和不对应答。
#define ERR_TH 0XE3 //本机读取温湿度时出错应答。即后面的数据不可靠
#define SUCC_ADDR 0XF1 //设置地址成功应答
#define SUCC_TH 0XF2 //表示温湿度读数正确。
#define ASK 0XF8 //应答
#define SYS_ADDR 0XAA //系统标志,表示该机的地址已经设置。
#define RA_FLAG 0X55 //上位机读本机地址时,在地址位发送该标志。
#define TIMING_5MS 0XEE00 //TIMING 5MS @ 11.0592MHz
#define TIMING_10MS 0XDC00 //TIMING 10MS @ 11.0592MHz
#define NUM_SEG 3 // 数码管个数
//*******************************************************************
//------------uart------------------------------
bit bit_ut_start = 0;
bit bit_ut_over = 0;
//----------ds18b20-------------------------------
bit bit_tpsensor = 0;
//-----------IAP---------------------------------------
bit bit_iap = 0;
bit bit_10ms = 0;
bit bit_100ms = 0;
bit bit_1s = 0;
bit bit_400ms = 0;
bit bit_10ms_over = 0;
bit bit_400ms_over = 0;
data UINT8 t0_10ms = 0;
data UINT8 t0_400ms = 0;
data UINT8 disbuff[3]; //显示缓冲,存放查找后的段码
data UINT8 buffer[10]; //uart buffer
data UINT8 seg_num = 0; //数码管点亮顺序
data UINT8 dabuff[10]; //数据缓冲
data UINT8 machine_addr; //local address
//---------------温度 ----------------
data SINT16 tp;
data SINT8 t ;
bit bit_disp; //显示标志
bit bit_relay;
UINT8 ut_num=0;
//code UINT8 table[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
code UINT8 table[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
void relay_os(bit bit_con);
//********************************************************************
void cpu_init()
{
relay_os(0);
INT_GLOBAL(0);
INT_T1(0);
INT_T0(0);
INT_UART(0);
P1 = 0xff;
P3 = 0xff;
setup_timer(T1_START_BY_TR | T1_TIMER | T1_MODE_2 | T0_START_BY_TR | T0_TIMER | T0_MODE_1);
#ifdef STC_12X2052X //定义使用STC12C2052单片机。
#ifdef EXT_1M //外部1MHz时钟
SET_T0_DIV_BY_1; //timer0/timer1 定时器的时钟直接使用外部时钟。不做分频
SET_T1_DIV_BY_1;
set_timer1(0xF3F3); //设置波特率4800
UART_RATE_MUL; //波特率翻倍
#endif
#endif
#ifdef EXT_11M //使用STC89C51单片机。11059200晶振
//set_timer1(0xFDFD); //9600
set_timer1(0xFAFA); //4800
#endif
T1_START;
setup_uart(UART_MODE_1); //UART工作于模式1
ENABLE_UART_RCV;
bit_iap = flsh_sector_rd(EEP_SECTOR1,2,dabuff);
if(!bit_iap)
flsh_sector_rd(EEP_SECTOR1,2,dabuff);
if(buffer[0] == SYS_ADDR)
{
machine_addr = dabuff[1];
}
else
machine_addr = ADDR;
set_timer0(TIMING_5MS);
T0_START;
INT_GLOBAL(1);
INT_UART(1);
INT_T0(1);
WDT_DIV_BY_128;
WDT_ENABLE;
WDT_CLR;
}
/*********************************************************************
/串口中断服务程序
//处理串口接收中断,对于发送中断不作处理
***********************************************************************/
void uart_service() interrupt 4 using 1
{
UINT8 tmp;
if(RI)
UART_RIIF_CLR ;
else
return;
tmp = rd_uart();
if(!bit_ut_start)
{
if(tmp == HEAD)
{
bit_ut_start = 1;
bit_ut_over = 0;
ut_num = 0;
}
}
else
{
buffer[ut_num] = rd_uart();
ut_num++;
/*
if(ut_num == 1)
{
if((buffer[0] != machine_addr) && (buffer[0] !=RA_FLAG)) //地址不符
{ //且地址不等于RA_FLAG.退出。RA_FLAG是读本机地址标志
ut_num = 0;
bit_ut_start = 0;
return;
}
} */
if(ut_num == 3)
{
bit_ut_over = 1 ; //接收完毕一帧数据
bit_ut_start = 0; //接着重新开始接收
ut_num = 0;
}
}
}
//----------------------------------------------------------------
void relay_os(bit bit_con)
{
if(bit_con)
{
con1=0;
con2=1;
bit_relay = 1;
}
else
{
con1 = 1;
con2 = 0;
bit_relay = 0;
}
delay_10clk(10000); //30~40ms
con1=0;
con2=0;
}
/*********************************************************************
使用ULN2003或者2803驱动,8位并口,输出反相。驱动电流200mA
每个数码管用一个驱动器。驱动器的控制端使用p1口。p1口留上拉位置。
扫描信号由p0口产生,使用上拉,驱动4953.
*********************************************************************/
void display()
{
SEG_DRV = 0Xf8; //SHUT LED
seg_num++;
if((seg_num>=3) )
{
seg_num = 0;
SEG_DRV = 0xf9;
}
else
{
SEG_DRV = 0XF8 + (seg_num<<1);
}
SEG_PARA = disbuff[seg_num];
}
/*********************************************************************/
void t0_service() interrupt 1 using 2
{
set_timer0(TIMING_5MS);
if(bit_disp)
{
display();
}
if(bit_10ms)
{
t0_10ms++;
if(t0_10ms >= 3)
{
bit_10ms_over = 1;
bit_10ms = 0;
t0_10ms = 0;
}
}
if(bit_400ms)
{
t0_400ms++;
if(t0_400ms >= 80)
{
bit_400ms_over = 1;
bit_400ms = 0;
t0_400ms = 0;
}
}
}
/**********************************************************************/
/********************************************************************
//
//通过串口,输出一帧数据到pc机
//参数:输出数据的缓冲地址,输出数据的长度,不包括校验和、帧头等。
//发送数据的格式:帧头+本机地址+数据长度+数据包+校验和
*********************************************************************/
void mcu2pc(UINT8 *p,UINT8 l)
{
UINT8 i,tmp;
en485 = 0; //485发送使能
delay_7clk(2);
uart_putc(HEAD);
uart_putc(machine_addr);
uart_putc(l); //数据长度。
tmp = HEAD + machine_addr + l;
for(i = 0;i<l ;i++)
{
uart_putc(*p); //p指向要发送的数据
tmp = tmp + *p;
p++;
}
uart_putc(tmp); //发送校验和。
en485 = 1; //485接收使能
}
/***********************************************************************************
//命令处理程序
************************************************************************************/
void cmd_process()
{
UINT8 i,tmp;
INT_UART(false); //禁止中断
if(buffer[0] != machine_addr)
{
if((buffer[0] != RA_FLAG) || (buffer[1] != READ_ADDR))
{
INT_UART(true);
return;
}
}
i = HEAD + buffer[0] + buffer[1]; //校验和
if( i != buffer[2])
{
INT_UART(true);
return;
}
switch(buffer[1])
{
case SET_ADDR: //设置地址
i = uart_getc();
tmp = uart_getc();
if( tmp != i)
{
// uart_putc(ERR_VERI);
i = ERR_VERI;
mcu2pc(&i,1);
INT_UART(true);
return;
}
buffer[1] = i;
buffer[0] = SYS_ADDR; //系统设置标志
bit_iap = flsh_sector_wr(EEP_SECTOR1,2,buffer);
if(bit_iap)
{
i = SUCC_ADDR;
mcu2pc(&i,1);
machine_addr = buffer[1];
//设置地址成功
}
else
{
i = ERR_ADDR;
mcu2pc(&i,1);
//设置地址失败
}
break;
case READ_ADDR: //读本机地址
mcu2pc(&machine_addr,1);
break;
case READ_T: //读温度
if(bit_tpsensor)
{
buffer[0] = ERR_TH;
}
else
{
buffer[0] = SUCC_TH; //读数据无误
}
buffer[1] = tp >> 8;
buffer[2] = tp & 0x00ff;
mcu2pc(buffer,3); //发送3个字节。状态+温度h+温度l
break;
case READ_S:
if(bit_tpsensor)
{
buffer[0] = ERR_TH;
}
else
{
buffer[0] = SUCC_TH; //读数据无误
}
buffer[1] = t;
mcu2pc(buffer,2); //发送3个字节。状态+温度h+温度l
break;
case OPEN:
relay_os(1);
buffer[0] = ASK;
mcu2pc(buffer,1);
break;
case SHUT:
relay_os(0);
buffer[0] = ASK;
mcu2pc(buffer,1);
break;
case TEST:
SEG_DRV = uart_getc() ;
break;
default:
break;
}
INT_UART(true);
}
/**************************************************************************/
void look_up_code()
{
if(dabuff[6]==0x01)
{
if(dabuff[2] == 0 && dabuff[3] == 0)
{
disbuff[0] = ~table[11]; //first seg dark
disbuff[1] = ~table[dabuff[4]] | 0x80; //个位显示在Q1
disbuff[2] = ~table[dabuff[5]]; //小数位显示在Q2
}
else if(dabuff[2] == 0 && dabuff[3] != 0)
{
disbuff[0] = ~table[dabuff[3]]; //十位显示在Q0
disbuff[1] = ~table[dabuff[4]] | 0x80; //个位显示在Q1
disbuff[2] = ~table[dabuff[5]]; //小数位显示在Q2
}
else if(dabuff[2] != 0)
{
disbuff[0] = ~table[dabuff[2]];
disbuff[1] = ~table[dabuff[3]];
disbuff[2] = ~table[dabuff[4]];
}
}
else if(dabuff[6] == 0x00)
{
disbuff[0] = ~table[10];
if(dabuff[3] == 0)
{
disbuff[1] = ~table[dabuff[4]] | 0x80;
disbuff[2] = ~table[dabuff[5]];
}
else
{
disbuff[1] = ~table[dabuff[3]];
disbuff[2] = ~table[dabuff[4]];
}
}
else
{
dabuff[6] = 0x01;
return;
}
}
/**************************************************************************/
void do_tem()
{
SINT8 tmp,tmp1;
ibus_reset();
read_rom(dabuff);
if(dabuff[0] != 0x28)
{
bit_tpsensor = 1;
return;
}
bit_tpsensor = 0;
read_scratchpad(dabuff);
if((dabuff[4]&0x60) != 0x40)
{
dabuff[0]=125;
dabuff[1]=-55;
dabuff[2]=0x5f; //1f->9bit/93.75ms;3f->10bit/187.5ms;5f->11bit/375ms;7f->12bit/750ms;
ibus_reset();
write_skip();
write_scratchpad(dabuff);
copy_scratchpad();
}
ibus_reset();
write_skip();
convert_t();
ibus_reset();
write_skip();
read_temperature(dabuff); //read temperature
tp = dabuff[1] << 8 | dabuff[0];
t = (dabuff[1] << 4) | (dabuff[0] >> 4);
dabuff[2]=dabuff[3]=dabuff[4]=dabuff[5] =dabuff[6]=0;
// 百位 十位 个位 小数位 状态位
tmp = t;
tmp1 = dabuff[0] & 0x0e;
if(tmp >= 0)
{
dabuff[6] = 0x01; //表示正数
while(tmp>=100)
{
tmp = tmp - 100; //温度大于等于100度.百位加1
dabuff[2]++;
}
while(tmp>=10)
{
tmp = tmp-10; //大于等于10度,十位加一
dabuff[3]++;
}
dabuff[4] = tmp; //个位就是剩下的数
}
else
{
dabuff[6] = 0x00; //温度值小于0度,负值
dabuff[2] = 10; //因为负值最小为-55度,没有百位,该位用作-号
while(t<=10)
{
tmp = tmp+10; //负10位,加10,直到十位为0.
dabuff[3]++;
}
while(tmp<0) //个位,不断加1,计数.知道为0
{
tmp = tmp+1;
dabuff[4]++;
}
tmp1 = tmp1 -1;
tmp1 &= 0x0f;
tmp1 = ~tmp1;
}
switch(tmp1)
{
case 0x0:
dabuff[5]=0;
break;
case 0x02:
dabuff[5] = 1;
break;
case 0x04:
dabuff[5] = 2;
break;
case 0x06:
dabuff[5] = 4;
break;
case 0x08:
dabuff[5] = 5;
break;
case 0x0a:
dabuff[5] = 7;
break;
case 0x0c:
dabuff[5] = 8;
break;
case 0x0e:
dabuff[5] = 9;
break;
default:
dabuff[5] = 6;
break;
}
look_up_code();
}
/**************************************************************************/
void main(void)
{
UINT8 i;
cpu_init();
bit_disp = 1; //start display scan
//----------------------------
while(1)
{
WDT_CLR;
do_tem();
if(bit_ut_over)
{
cmd_process();
bit_ut_over = 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -