首先,简要描述一下所实现的功能。系统采用DS18B20传感器测量实时温度,将测量的温度显示在LCD1602显示器上。此外,还用了IIC协议的EEPROM模块24LC256存储温度的历史值,存储深度为10000.也就是从系统开始运行,就实时将测量值存入EEPROM里面,直到存满10000个值,新值再从0开始覆盖旧值。存储起来的历史数据可以通过按键触发,发送到串口进行显示。
整个设计的电路图如下所示:
接下来就是思路及代码讲解。
首先看如何配置按键吧。
从电路图中可以看出,按键被我接在了RB2口,所以关注PIC单片机的管脚B相关寄存器即可。
上面是官方文档中,关于PORTB的描述。首先PORTB是8位宽的双向端口,可以配置为输入模式或者输出模式。寄存器TRISB就是控制管脚的输出方向的。当配置为1时,控制对应的管脚为输入模式,为0时,控制对应的管脚为输出模式。PORTB的所有管脚都有内部上拉的控制,通过OPTION_REG寄存器的第7位控制。将该位清0,代表使能内部上拉。当PORTB配置为输出模式时,自动清除内部上拉。(需要注意的是,要配置管脚为输入模式,就必须使能内部上拉,否则读不出IO口的电平状态!)
由于我用的是RB2,所以我关于PORTB的配置如下:
接下来就是配置串口。
USART,是通用同步异步接收器的简称,它是一种串行通信接口,可以与外围的串口通信设备进行数据交换。USART可以配置为一下几种工作方式;
异步(全双工)
同步主机(半双工)
同步从机(半双工)
和它相关的寄存器有:
TXSTA:发送状态和控制寄存器。
bit7: 时钟源选择位。如果是异步模式就不关心这一位,如果是同步模式,该位为1代表主机模式,为0代表从机模式,时钟源来自于外部。
bit6: 选择发送数据的长度。为0的话,代表发送的数据是8位。
bit5:是否使能发送模式。
bit4: 选择工作模式,是同步模式还是异步模式。
bit3: 未实现。
bit2: 高波特率选择位。如果是同步模式下,该位不关心。
bit1: 发送移位寄存器空/满标志
bit0: 发送数据的第九位,可以是奇偶校验位.
RCSTA: 接收状态和控制寄存器。
bit7: 串行口使能位
bit6: 接收数据长度选择位。1代表接收数据长度为8位。
bit5:单接收使能位。在同步从机模式下不必关注该位。
bit4: 连续接收使能位
bit3: 地址检测使能位
bit2: 帧错误检测位
bit1: 溢出错误位
bit0: 接收数据的第九位.
SPBRG 波特率控制寄存器。
其中,波特率的计算如下:
X的值就是寄存器 SPBRG里面的值,范围是0-255.对于异步高速模式,可以查表得到常用的波特率下寄存器 SPBRG的值为多少。
本次对串口的配置如下:
接下来就是DS18B20测温模块了。关于该模块的资料,网上有很多,这里就不介绍了。主要讲下它的工作流程:
初始化DS18B20
执行ROM指令
执行DS18B20功能指令
第二步执行ROM指令,也就是访问每个DS18B20,搜索64位序列号,读取匹配的序列号值,然后匹配对应的DS18B20,如果我们仅仅使用单个DS18B20,可以直接跳过ROM指令。而跳过ROM指令的字节是0xCC。
然后关于它的读写时序,这里也不做过多介绍,直接给出PIC单片机驱动DS18B20的代码如下:
再往下就是EEPROM模块啦。
这个模块使用的是IIC协议,可以参考该模块数据手册。不详细展开,会用即可。
我们在使用的的时候,配置一下PIC单片机的硬件IIC即可。
关于LCD显示器的部分,可以看我写的PIC第一篇文章。
仿真效果图如下:
按下按键后
主程序代码如下:文章来源:https://www.toymoban.com/news/detail-768399.html
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include <xc.h>
#include "ee302lcd.h" // Include LCD header file
#include <stdio.h> // Include Standard I/O header file
#include "I2C_EE302.h"
#define uchar unsigned char
#define uint unsigned int
#define KEY1 RB2 //label RB2 as key1
#define temp_h (PORTC|=0x20) //DS18B20--->RC5
#define temp_l (PORTC&=0xdf)
#define temp_o (TRISC&=0xdf)
#define temp_i (TRISC|=0x20)
unsigned char dat1,dat2;//保存读出的温度z
unsigned long int dat;
unsigned char outString[5]; //character array for LCD string
unsigned char outString2[5]; //存放光照阈值 用于显示
void delayms(int x) //4M晶振下,延时1ms
{
int y,z;
for(y=x;y>0;y--)
for(z=110;z>0;z--);
}
void Ds18b20_reset(void)//DS18B20初始化
{
uint count;
uchar temp;
uchar i,flag=1;
temp_o;
temp_l;
for(count=60;count>0;count--);//延时480us
temp_i;
while(flag)
{
if(RC5)
flag=1;
else
flag=0;
}
for(count=60;count>0;count--);//延时480us
}
void Ds18b20_write(uchar datt)//向DS18B20写一个字节
{
uchar count;
uchar i;
temp_o;
for(i=8;i>0;i--)
{
temp_o;
temp_l;
for(count=1;count>0;count--);
if(datt&0x01==0x01)
temp_i;
else
{
temp_o;
temp_l;
}
for(count=23;count>0;count--);//延时60us
temp_i;
for(count=1;count>0;count--);
datt>>=1;
}
}
uchar Ds18b20_read(void) //从DS18B20读一个字节
{
uchar i,datt;
uchar count;
for(i=8;i>0;i--)
{
datt>>=1;
temp_o;
temp_l;
for(count=1;count>0;count--);
temp_i;//改为输入方向时,上拉电阻把数据线拉高,释放总线,此语句必须有,参考datasheet的P15
for(count=1;count>0;count--);
if(RC5)
datt|=0x80;
for(count=23;count>0;count--);//延时60us
}
return datt;
}
//串口发送
void transmit_string (char *p)
{
while (*p != '\0') //While string does not equal Null character
//do the following.
{
while (!TXIF); //Wait until TXREG empty.
TXREG = *p; //Load TXREG with character from string pointed to
p++; // by p, then increment p.
}
}
void main(void)
{
int addr=0;
int i=0;
int dat_read=0;
i2c_init(); //do i2c intialisation, TRISC modified here
Lcd8_Init(); // Required initialisation of LCD to 8-bit mode
TRISB=0x0C; // Set PORTB bit 2 3 as input for switch
PORTB=0X0C; //enable internal pull up
OPTION_REG=0X00; //turn on pull up in port B
//iic
TRISC |= 0x18; // RC6 and RC7 must be configured as inputs to enable the UART
// RC4 and RC3 high from I2C_init
TRISA=0x04; // Set PORTA bit 3 as input for AN2
ADCON0 = 0b01010001; // ADCS1:ADCS0 set to 0:1 for Tosc x8 (Fosc/8)
// Channel 2
// ADC On
ADCON1 = 0b00000010; // Left justified result
// ADCS2 = 0 for Tosc x8 (Fosc/8)
// RA2/AN2 selected as analog input
// Vref+ : Vdd Vref- : Vss
// AN7, AN6 and AN5 selected for Digital I/O for LCD
//USART
TRISC |= 0xC0; // RC6 and RC7 must be configured as inputs to enable the UART
TXSTA = 0x24; // Set TXEN and BRGH
RCSTA = 0x80; // Enable serial port by setting SPEN bit
SPBRG = 0x19; // Select 9600 baud rate.
while(1)
{
Ds18b20_reset();
Ds18b20_write(0xcc);
Ds18b20_write(0x44);//发送温度转换命令
delayms(1000);//延时1s,等待温度转换完成
Ds18b20_reset();
Ds18b20_write(0xcc);
Ds18b20_write(0xbe);//发送读温度寄存器命令
dat1=Ds18b20_read();
dat2=Ds18b20_read();
dat=(dat2*256+dat1)*(0.0625*10);
write_ext_eeprom(addr/256, addr%256, dat); //store the data to eeprom
addr++;
if(addr==10000)
addr=0; //存储长度为10000
dat1=dat/10;
dat2=dat%10;
sprintf(outString,"%d.%d",dat1,dat2);
Lcd8_Clear(); //clear LCD
Lcd8_Write_String(outString);
if(KEY1==0)
{
__delay_ms(100);
if(KEY1==0)
{
for(i=0;i<addr;i++)
{
dat_read=read_ext_eeprom(i/256, i%256); // Read byte at address 0x0001 on EEPROM
sprintf(outString2,"%d\r\n",dat_read);
transmit_string(outString2); //将读到的存储值通过串口打印出去
__delay_ms(100);
}
}
}
}
}
需要完整工程和仿真文件的可以私信,或者在评论区留言!!文章来源地址https://www.toymoban.com/news/detail-768399.html
到了这里,关于PIC单片机项目(2)——基于PIC16F877A的温度测量与存储装置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!