#include <pic.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
__CONFIG(HS&WDTDIS&LVPDIS);
#define uint unsigned int
#define uchar unsigned char
#define E RB3 //1602液晶的E脚接在RB3口上
#define RW RB4 //1602液晶的RW脚接在RB4口上
#define RS RB5 //1602液晶的RS脚接在RB5口上
#define BEEP RC1 //蜂鸣器报警口
uchar HAND[]="AT";
uchar YING[]="AT+CMGF=1
";
uchar LENGTH[]="AT+CMGS=18203230290
";
uchar NR[]="T: *C Vol: , V W: S";
//A/D转换用寄存器设置
uint ADbuf,bai,shi,ge; //设置16位的unsigend int型寄存器用来暂存转换结果
double i_val=0;
uchar adcbuf[16];
uchar buf;
uchar q=0; //中断时间控制
uchar d; //采样存数组
uchar m=0; //控制窗户先开后关
uchar temp1; //采集到的温度高8位
uchar temp2; //采集到的温度低8位
//转换后的温度值小数点部分查表
const uchar tablexiao[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};
const uchar shun[8]=
{ //定义表格一定要使用const,这样会做到程序存储区中
0x20, //表格第1步数据0B00100000
0x30, //表格第2步数据0B00110000
0x10, //表格第3步数据0B00010000
0x18, //表格第4步数据0B00011000
0x08, //表格第5步数据0B00001000
0x0c, //表格第6步数据0B00001100
0x04, //表格第7步数据0B00000100
0x24, //表格第8步数据0B00100100
};
const uchar ni[8]=
{ //定义表格一定要使用const,这样会做到程序存储区中
0x04, //表格第1步数据0B00000100
0x0c, //表格第2步数据0B00001100
0x08, //表格第3步数据0B00001000
0x18, //表格第4步数据0B00011000
0x10, //表格第5步数据0B00010000
0x30, //表格第6步数据0B00110000
0x20, //表格第7步数据0B00100000
0x24, //表格第8步数据0B00100100
};
void delay35(uint ms)// 延时子程序
{
uchar i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
//1602液晶用延时函数
void Delay1602(uint t)
{
uint k; //定义一个16位寄存器用来做延时用
for(k=0;k<t;k++); //延时
}
//1602液晶忙检测函数
void LCD1602_busy(void)
{
TRISD7=1; //将RD7口设置为输入口,为读做准备
RS=0; //RS=0、RW=1、E=1时,忙信号输出到DB7,由RD7读入
RW=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由RD7读入
E=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由RD7读入
while(RD7==1); //由RD7读入1,表示1602液晶忙,需要等待
E=0; //读完以后,恢复E的电平
TRISD7=0; //将RD7口设置为输出口
}
//名称:1602写命令函数
void LCD1602_Write_com(uchar combuf)
{
RS=0; //选择指令寄存器
RW=0; //选择写状态
PORTD=combuf; //将命令字通过RD口送至DB
E=1; //E高电平将命令字写入1602液晶
asm("NOP"); //添加一个空操作,使高电平至少维持1us
E=0; //写完以后,恢复E的电平
}
//1602写命令函数(带忙检测)
void LCD1602_Write_com_busy(uchar combuf)
{
LCD1602_busy(); //调用忙检测函数
LCD1602_Write_com(combuf); //调用忙检测函数
}
//名称:1602写数据函数(带忙检测)
void LCD1602_Write_data_busy(uchar databuf)
{
LCD1602_busy(); //调用忙检测函数
RS=1; //选择数据寄存器
RW=0; //选择写状态
PORTD=databuf; //将命令字通过RD口送至DB
E=1; //E高电平将命令字写入1602液晶
asm("NOP"); //添加一个空操作,使高电平至少维持1us
E=0; //写完以后,恢复E的电平
}
//1602液晶显示地址写函数
void LCD1602_Write_address(uchar x,uchar y)
{
x&=0x0f; //列地址限制在0-15间
y&=0x01; //行地址限制在0-1间
if(y==0) //如果是第一行
LCD1602_Write_com_busy(x|0x80); //将列地址写入
else //如果是第二行
LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入
}
//1602液晶初始化函数
void LCD1602_init(void)
{
Delay1602(1500); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
Delay1602(500); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
Delay1602(500); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
LCD1602_Write_com_busy(0x38); //8位数据总线,两行显示模式,5*7点阵显示
LCD1602_Write_com_busy(0x08); //显示功能关,无光标
LCD1602_Write_com_busy(0x01); //清屏
LCD1602_Write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动
LCD1602_Write_com_busy(0x0C); //显示功能开,无光标
}
//1602液晶指定地址显示函数
void LCD1602_Disp(uchar x,uchar y,uchar buf)
{
LCD1602_Write_address(x,y); //先将地址信息写入
LCD1602_Write_data_busy(buf); //再写入要显示的数据
}
//DS18B20用延时函数
void delay(uchar x,uchar y)
{
uchar z;
do{
z=y;
do{
;
}while(--z);
}while(--x);
}
//复位DS18B20函数
uchar reset(void)
{
uchar outbit;
TRISA4=0; //设置RA4位输出口
RA4=0; //设置RA4=0;
delay(2,70); //延时503us
TRISA4=1; //设置RA4为输入口,以释放总线等电阻拉高总线
delay(2,8); //延时70us
if(RA4==1) outbit=0; //没有接收到应答信号,继续复位
else outbit=1; //接收到应答信号
delay(2,60); //延时430us
return outbit; //带参数返回,如果接收到应答,返回1,否则返回0
}
//写字节函数
void write_byte(uchar val)
{
uchar f;
uchar temp;
for(f=8;f>0;f--)
{
temp=val&0x01; //最低位移出
TRISA4=0; //设置RA4位输出口
RA4=0; //设置RA4=0;
NOP();NOP();NOP();NOP();NOP(); //从高拉至低电平,产生写时间隙
if(temp==1) TRISA4=1; //如果写1,拉高电平
delay(2,7); //延时63us
TRISA4=1; //设置RA4为输入口,以释放总线等电阻拉高总线
NOP();NOP();
val=val>>1; //右移一位
}
}
//读字节函数
uchar read_byte(void)
{
uchar e;
uchar value=0; //读出温度
for(e=8;e>0;e--)
{
value>>=1;
TRISA4=0; //设置RA4位输出口
RA4=0; //设置RA4=0;
NOP();NOP();NOP();NOP();NOP();NOP(); //6us
TRISA4=1; //设置RA4为输入口
NOP();
NOP();
NOP();
NOP(); //4us
if(RA4==1) value|=0x80; //如果接收到数据为1,从最高位往右移
delay(2,7); //63us
}
return(value);
}
//启动读温度函数
void convert_T(void)
{
if(reset()==1) //如果复位成功
{
write_byte(0xcc); // 跳过多器件识别
write_byte(0x44); // 启动温度转换
}
}
//读温度函数
void read_T(void)
{
uchar Lsb,Msb;
if(reset()==1)
{
write_byte(0xcc); // 跳过多器件识别
write_byte(0xbe); // 读暂存器
Lsb=read_byte(); // 低字节
Msb=read_byte(); // 高字节
temp2=Lsb&0x0f; //LSB的低4位为小数部分
temp1=(Lsb>>4)|(Msb<<4);//LSB的高4位和MSB拼成整数部分
}
}
//电机正反转查表函数
void shun1(void)
{
uint a,b;
for(b=1200;b>0;b--)
for(a=0;a<7;a++) //a做加1操作,并限制在0-7以内
{ Delay1602(180);
PORTC=shun[a];
}
}
void ni1(void)
{
uint a,b;
for(b=1200;b>0;b--)
for(a=0;a<7;a++)
{Delay1602(180);
PORTC=ni[a];
}
}
void USART_BUF(void)
{
SPBRG=25; //设置波特率为9600,误差0.16%
BRGH=1; //设置高速波特率
SYNC=0; //SYNC=0为异步模式,SYNC=1为同步模式
SPEN=1; //允许串口操作
CREN=1; //CREN=0禁止连续接收,CREN=1允许连续接收
TXIE=0; //禁止发送中断
RCIE=0; //禁止接收中断
TX9=0; //TX9=0为8位发送,TX9=1为9位发送
RX9=0; //RX9=0为8位接收,RX9=1为9位接收
TXEN=1; //TXEN=0为禁止发送,TXEN=1为允许发送
}
void A_D(void)
{
ADCON1=0B00001110; //RA0为A/D输入口;ADFM=0,转换后数据左移,ADRESH为高8位数据
ADIE=0; //禁止A/D中断
}
Print_Char(uchar ch)//发送单个字符
{
TXREG=ch; //送入缓冲区
while(TRMT==0); //等待发送完毕
}
Print_Str(uchar *str)//发送字符串
{
while(*str!=' ')
{
Print_Char(*str);
delay35(10);
str++;
}
}
void send_mess(void)
{
delay35(10);
Print_Str(HAND); //单片机与TC35模块连接
delay35(100);
Print_Str(YING); //发英文短信
delay35(200);
Print_Str(LENGTH);
delay35(200);
Print_Str(NR);
delay35(200);
Print_Char(0x1a);
delay35(100);
}
void A_DZHUANHUA(void)
{
ADCON0=0B00000001; //选择AN0通道准备进行A/D转换,启动A/D模块
asm("NOP");asm("NOP");asm("NOP");asm("NOP"); //略做延时
ADGO=1; //开始进行A/D转换
while(ADGO) continue; //等待A/D转换结束
adcbuf[d]=ADRESH; //将8位A/D转换结果暂存在数组中
}
void tmr1(void)
{
TMR1CS=1; //外部计数
T1CKPS0=0; //1:1预分频比,T1CKPS0=0
T1CKPS1=0; //1:1预分频比,T1CKPS1=0
TMR1H=0xFF; //置初值
TMR1L=0xD0;
TMR1ON=1; //启动定时器T1
TMR1IF=0; //清除T1的中断标志
TMR1IE=0; //禁止T1中断
}
void tmr0(void)
{
T0CS=0; //TMRO时钟源选择内部指令周期时钟(Fosc/4)
PSA=0; //预分频器分配给TMR0模块
PS0=1; //TMR0预分频比1:256,PS0=1
PS1=1; //TMR0预分频比1:256,PS1=1
PS2=1; //TMR0预分频比1:256,PS2=1
TMR0=0x0D; //定时65536微秒,置初值为256-256+13 对于13是怎么来的,请翻阅资料刘和平著书关于定时那部分,会有详细介绍
T0IF=0; //清除TMR0的中断标志
T0IE=0; //禁止TMR0中断
}
void XIAN(void)
{
LCD1602_Disp(1,1,'V');
LCD1602_Disp(2,1,'o');
LCD1602_Disp(3,1,':');
LCD1602_Disp(5,1,'.');
LCD1602_Disp(8,1,'V');
LCD1602_Disp(12,1,'W');
LCD1602_Disp(13,1,':');
LCD1602_Disp(15,1,'S');
LCD1602_Disp(1,0,'T');
LCD1602_Disp(2,0,':');
LCD1602_Disp(5,0,'.');
LCD1602_Disp(7,0,0xdf);
LCD1602_Disp(8,0,0x43);
}
void ad(void)
{
for(d=0;d<16;d++) //连续采样16次,然后取平均数
{
A_DZHUANHUA(); //***启动一次A/D转换***
}
ADbuf=0;
for(d=0;d<16;d++)
{
ADbuf+=adcbuf[d];
}
ADbuf=ADbuf/16;
i_val=(double)ADbuf;
i_val=(i_val*500)/255;
if(i_val>999) i_val=999;
ADbuf=(int)i_val;
bai=(ADbuf/100)+0x30;
NR[12]=bai;
shi=(ADbuf%100)/10+0x30;
NR[14]=shi;
ge=(ADbuf%10)+0x30;
NR[15]=ge;
LCD1602_Disp(4,1,bai); //百位
LCD1602_Disp(6,1,shi); //十位
LCD1602_Disp(7,1,ge); //个位
}
void wendu(void)
{
convert_T(); //启动温度转换
delay(25,250); //延时
read_T(); //读温度数据
if(temp1>99) temp1=99; //这里我们只显示2位整数部分,所以限定在99度
if(temp2>15) temp2=0; //限定范围,以免查表溢出
buf=temp1/10;
buf+=0x30;
NR[2]=buf;
LCD1602_Disp(3,0,buf); //温度整数部分十位
buf=temp1%10;
buf+=0x30;
NR[3]=buf;
LCD1602_Disp(4,0,buf); //温度整数部分个位
buf=tablexiao[temp2&0x0f];
buf+=0x30;
LCD1602_Disp(6,0,buf); //温度小数部分
}
void fengsu(void)
{
if(T0IF==1) //需要进一步判断是否是T0中断
{
TMR0=0x13; //定时器中断后,要重置初值,以备下次中断
T0IF=0; //清中断标志位,以备下次中断
if(++q>15) //65536us查询一次,再计次15次后就是0.98304s
{
q=0;
if(TMR1L>=0xD6) //显示风级
{LCD1602_Disp(14,1,'6');NR[20]='6';}
else if(TMR1L>=0xD5)
{LCD1602_Disp(14,1,'5');NR[20]='5';}
else if(TMR1L>=0xD4)
{LCD1602_Disp(14,1,'4');NR[20]='4';}
else if(TMR1L>=0xD3)
{LCD1602_Disp(14,1,'3');NR[20]='3';}
else if(TMR1L>=0xD2)
{LCD1602_Disp(14,1,'2');NR[20]='2';}
else if(TMR1L>=0xD1)
{LCD1602_Disp(14,1,'1');NR[20]='1';}
else if(TMR1L>=0xD0)
{LCD1602_Disp(14,1,'0');NR[20]='0';}
if((m==0)&&((i_val>100)|(temp1>26)))
{
LCD1602_Disp(11,0,'O');
LCD1602_Disp(12,0,'P');
LCD1602_Disp(13,0,'E');
LCD1602_Disp(14,0,'N');
BEEP=1;
Delay1602(60000);
Delay1602(60000);
BEEP=0;
send_mess();
ni1();
m=m+1;
}
if((m==1)&&((TMR1L>0xD3)|(temp1<10)))
{
LCD1602_Disp(11,0,'C');
LCD1602_Disp(12,0,'L');
LCD1602_Disp(13,0,'O');
LCD1602_Disp(14,0,'S');
LCD1602_Disp(15,0,'E');
shun1();
m=m-1;
}
TMR1H=0xFF; //重置初值 TMR1 16位计数器
TMR1L=0xD0; //重置初值
}
}
}
void main(void) //主函数,单片机开机后就是从这个函数开始运行
{
TRISA=0B11111111; //初始化RA5-RA0的输入输出方向
PORTA=0B00000000; //初始化RA5-RA0数值
PORTB=0B00000000; //初始化RB7-RB0的数值
TRISB=0B11000111; //初始化RB7-RB0的输入输出方向
TRISC=0B11000001; //初始化RC7-RC0的输入输出方向
PORTC=0B00000000; //初始化RC7-RC0的数值
TRISD=0B00000000; //初始化RC7-RC0的输入输出方向
PORTD=0B00000000; //初始化RC7-RC0的数值
LCD1602_init(); //1602液晶初始化函数
A_D(); //****A/D模块初始化****
tmr0(); //定时器TMR0初始化
tmr1(); //定时器TMR1初始化
USART_BUF(); //串口初始化
while(1) //死循环,单片机初始化后,将一直运行这个死循环
{
ad();
XIAN();
wendu();
fengsu();
}
}
#include <pic.h> //调用PIC16F87XA单片机的头文件
__CONFIG(HS&WDTDIS&LVPDIS); //写配置子
unsigned int q;
void Delay1602(unsigned int t)
{
unsigned int k; //定义一个16位寄存器用来做延时用
for(k=0;k<t;k++); //延时
}
}
const unsigned char shun[8]=
{
0x81, //表格第1步数据0B10000000 顺时针
0xc1, //表格第2步数据0B11000000
0x41, //表格第3步数据0B01000000
0x61, //表格第4步数据0B01100000
0x21, //表格第5步数据0B00100000
0x31, //表格第6步数据0B00110000
0x11, //表格第7步数据0B00010000
0x91, //表格第8步数据0B10010000
};
const unsigned char ni[8]=
{
0x11, //表格第1步数据0B00010000 逆时针
0x31, //表格第2步数据0B00110000
0x21, //表格第3步数据0B00100000
0x61, //表格第4步数据0B01100000
0x41, //表格第5步数据0B01000000
0xc1, //表格第6步数据0B11000000
0x81, //表格第7步数据0B10000000
0x91, //表格第8步数据0B10010000
};
void shun1(void)
{
unsigned int a,b;
for(b=500;b>0;b--)
for(a=0;a<7;a++) //a做加1操作,并限制在0-7以内
{ Delay1602(200);
PORTC=shun[a];
}
}
void ni1(void)
{
unsigned int a,b;
for(b=500;b>0;b--)
for(a=0;a<7;a++)
{Delay1602(200);
PORTC=ni[a];
}
}
//名称:中断服务程序
void interrupt ISR(void) //PIC单片机的所有中断都是这一个入口
{
if(T0IF==1) //需要进一步判断是否是T0中断
{
TMR0=0x13; //定时器中断后,要重置初值,以备下次中断
T0IF=0; //清中断标志位,以备下次中断
//***此处用户自行添加定时器T0中断处理程序***
if(++q>100) //65536us中断一次,再计次100次后就是6.5536秒
{
q=0;
//***风速计数中断部分程序***
if(TMR1L>0xE4) //TMR1 16位计数器
{
ni1();
}
TMR1H=0xFF; //重置初值
TMR1L=0xE0; //重置初值
}
}
}
void main(void) //主函数,单片机开机后就是从这个函数开始运行
{
TRISC=0B00001111; //初始化RC7-RC0的输入输出方向
PORTC=0B00001111; //初始化RC7-RC0的数
//***定时器TMR0初始化***
T0CS=0; //TMRO时钟源选择内部指令周期时钟(Fosc/4)
PSA=0; //预分频器分配给TMR0模块
PS0=1; //TMR0预分频比1:256,PS0=1
PS1=1; //TMR0预分频比1:256,PS1=1
PS2=1; //TMR0预分频比1:256,PS2=1
TMR0=0x0D; //定时65536微秒,置初值为256-256+13
T0IF=0; //清除TMR0的中断标志
T0IE=1; //TMR0中断允许
//***定时器TMR1初始化***
TMR1CS=1; //外部计数
T1CKPS0=0; //1:1预分频比,T1CKPS0=0
T1CKPS1=0; //1:1预分频比,T1CKPS1=0
TMR1H=0xFF; //置初值
TMR1L=0xE0;
TMR1ON=1; //启动定时器T1
TMR1IF=0; //清除T1的中断标志
TMR1IE=0; //不允许T1中断
PEIE=0; //不允许外设中断,TMR1属于外设中断范围
GIE=1; //开全局中断
while(1) //死循环,单片机初始化后,将一直运行这个死循环
{
}
}
此帖出自
小平头技术问答
Clean: Deleted file "E:PICProjectpic.mcs".
Clean: Done.
Executing: "e:picpiccBINPICC.EXE" -C -E"pic.cce" "pic.c" -O"pic.obj" -Zg9 -O -ASMLIST -Q -MPLAB -16F877A
Executing: "e:picpiccBINPICC.EXE" -E"pic.lde" "E:PICProjectpic.obj" -M"pic.map" -O"pic.cof" -O"pic.hex" -Q -MPLAB -16F877A
BUILD FAILED: Thu May 08 12:08:01 2014
第二个编译错误提示Clean: Deleting intermediary and output files.
Clean: Deleted file "E:PICfengpic.mcs".
Clean: Done.
Executing: "e:picpiccBINPICC.EXE" -C -E"pic.cce" "pic.c" -O"pic.obj" -Zg9 -O -ASMLIST -Q -MPLAB -16F877A
Halting build on first failure as requested.
BUILD FAILED: Thu May 08 12:06:04 2014
一周热门 更多>