I2C存储器读写(计数器,并能断电存储)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
任务二:I2C存储器读写(计数器,并能断电存储)之阿布丰王创作
实验原理
1)I2C总线概述
I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需
的包括总线判决和高低速器件同步功能的高性能串行总线.
2)I2C信号线
I2C总线只有两根双向信号线.一根是数据线SDA,另一根是时钟线SCL.I2C总线通过上拉电阻接正电源.当总线空闲时,两根线均为高电平.连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系.
图 1 I2C总线框图
3)I2C总线的数据传送
a)数据位的有效性规定
I2C总线进行数据传送时,时钟信号为高电平期间,数据
线上的数据必需坚持稳定,只有在时钟线上的信号为低电平
期间,数据线上的高电平或低电平状态才允许变动.
图 2 SDA与SCL的工作时序图
b) 起始和终止信号
SCL线为高电平期间,SDA线由高电平向低电平的变动暗
示起始信号
SCL线为高电平期间,SDA线由低电平向高电平的变动暗示终止信号.起始和终止信号都是由主机发出的,在起始信号发生后,总线就处于被占用的状态;在终止信号发生后,总线就处于空闲状态.
c) I2C总线的数据传送速率
I2C总线的通信速率受主机控制,能快能慢,最高速率限制为100Kb/s
d) I2C总线的数据传送格式
主机向从机发送数据
从机向主机发送数据
图 3 I2C总线的数据传送格式
S:起始位 SA: 从机地址,7位
W/:写标识表记标帜位,1位 R:读标识表记标帜位,1位
A:应答位,1位 A/:非应答位,1位
D:数据,8位 P:停止位
阴影:主机发生的信号无阴影:从机发生的信号4)总线的寻址
I2C总线协议有明确的规定:采纳7位的寻址字节(寻址字节是起始信号后的第一个字节).
寻址字节的位界说
D7~D1位组成从机的地址.D0位是数据传送方向位,为“0”时暗示主机
向从机写数据,为“1”时暗示主机由从机读数据.
主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比力,如果相同,则认为自己正被主机寻址,根据R/位将自己确定为发送器或接收器.
从机的地址由固定部份和可编程部份组成.在一个系统中可能希望接入多
个相同的从机,从机地址中可编程部份决定了可接入总线该类器件的最年夜数目.如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中.
任务三:
要求:设计一个简单系统,每10S进行温度收集(结合电路与法式,分析指标),在液晶屏上显示以后温度和前一状态的温度,并将结果存入存储器,具备可将温度的存储结果与PC机通讯和数据发送功能,可以使用键盘设定温度高低限制值,到达限制值时报警.
一、实验设计思路
二、实验内容
1、蜂鸣器工作原理
蜂鸣器发声原理是电流通过电磁线圈,使电磁线圈发生磁场来驱动振动膜发声的,因此需要一定的电流才华驱动它,单片机
IO引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放年夜的电路.原理图见图:如图所示,蜂鸣器的负极经电阻R3接地,蜂鸣器的正极接到三极管的集电极C,三极管的基级B经过限流电阻R2后由单片机的P1.3引脚控制,当P1.3输出高电平时,三极管Q1截止,没有电流流过线圈,蜂鸣器不发声;当P1.3输出低电平时,三极管导通,这样蜂鸣器的电流形成回路,发作声音.因此,我们可以通过法式控制P1.3脚的电平来使蜂鸣器发作声音和关闭.法式中改变单片机P1.3引脚输出波形的频率,就可以调整控制蜂鸣器音调,发生各种分歧音色、音调的声音.另外,改变P1.3输出电平的高低电平占空比,则可以控制蜂鸣器的声音年夜小.
2、SP2键盘控制
数据格式
数据发送时序
一个键盘发送值的例子:通码和断码是以什么样的序列发送到你的计算机从而使得字符G 呈现在你的字处置软件里的呢?因为这是一个年夜写字母,需要发生这样的事件次第:按下
Shift 键-按下G键-释放G 键-释放Shift 键.与这些时间相关的扫描码如下:Shift 键的通码12h,G 键的通码34h ,G 键的断码F0h 34h ,Shift 键的断码F0h 12h .因此发送到你的计算机的数据应该是:
12h 34h F0h 34h F0h 12h
3、DS18B20温度传感器
DS18B20工作原理及应用:
DS18B20的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强.其一个工作周期可分为两个部份,即温度检测和数据处置.在讲解其工作流程之前我们有需要了解18B20的内部存储器资源.18B20共有三种形态的存储器资源,它们分别是:
ROM 只读存储器,用于寄存DS18B20ID编码,其前8位是单线系列编码(DS18B20的编码是19H),后面48位是芯片唯一的序列号,最后8位是以上56的位的CRC码(冗余校验).数据在生产时设置不由用户更改.DS18B20共64位ROM.
RAM 数据暂存器,用于内部计算和数据存取,数据在失落电后丧失,DS18B20共9个字节RAM,每个字节为8位.第1、2个字节是温度转换后的数据值信息,第3、4个字节是用户EEPROM(经常使用于温度报警值贮存)的镜像.在上电复位时其值将被刷新.第5个字节则是用户第3个EEPROM的镜像.第6、7、8个字节为计数寄存器,是为了让用户获得更高的温度分辨率而设计的,同样也是内
部温度转换、计算的暂存单位.第9个字节为前8个字节的CRC 码.EEPROM 非易失性记忆体,用于寄存长期需要保管的数据,上下限温度报警值和校验数据,DS18B20共3位EEPROM,并在RAM都存在镜像,以方便用户把持.
4、LCD1602液晶显示
读写把持时序如图所示
图三:读把持时序
图四:写把持时序附录一:(任务二法式)
#include <p18f452.h>
#include <i2c.h>
#define uint unsigned int
#define uchar unsigned char
#define e PORTBbits.RB3//液晶屏e端接RB3
#define rw PORTBbits.RB4//液晶屏rw端接RB4
#define rs PORTBbits.RB5//液晶屏rs端接RB5
void disp(uchar num1,uchar num2,uchar num3);
void delay(uint z);
void disp_init(void); //液晶屏初始化
void write_com(uchar com);//对液晶屏写指令
void write_data(uchar dat);//写数据
void main(void)
{
unsigned int lednum=0,x,tt=0; //lednum 显示的数据,x 24c02读到的数据,tt时间累加
unsigned int a1=0,a2=0,a3=0; //显示位数个十百 disp_init();//1602的初始化
OpenI2C(MASTER, SLEW_ON);//I2C 的初始化
SSPADD = 9; //频率为400KHZ
T0CONbits.TMR0ON=0;//关闭TIMER0 T0CONbits.T08BIT=0;//配置为16位计数模式
T0CONbits.T0CS=0;//选择内部时钟源即按时模式
TMR0H=(65536-10000)/256;//按时5us TMR0L=(65536-10000)%256;
INTCONbits.TMR0IF=0;//清TIMER0溢出中断标识表记标帜位
T0CONbits.TMR0ON=1;//使能TIMER0 while(1)
{
x = EERandomRead(0xA0,0x03);//读数据,0XA0为器件地址 0X03为存储地址 if(INTCONbits.TMR0IF==1)
//TIMER0溢出中断标识表记标帜位为1 {
INTCONbits.TMR0IF=0;//清TIMER0溢出中断标识表记标帜位
TMR0H=(65536-
10000)/256;//5us*10000=50ms
TMR0L=(65536-10000)%256;
tt++;
if(tt==20)//1s
{
tt=0;
x++;
if(x==256)
{
x=0;
}
EEByteWrite(0xA0, 0x03,x); //写数据
EEAckPolling(0xA0);//应答
}
}
lednum = EERandomRead(0xA0,0x03);//防止断电遗失
a1=lednum/100;//百位上的数字
a2=lednum%100/10;//十位上的数字
a3=lednum%10;//个位上的数字
disp(a1,a2,a3);//显示
}
}
void write_com(uchar com)//LED1602控制字输入
{
TRISB=0b000000000;
//TRISB=0b00010000;
TRISD=0;
e=0;
rw=0;
rs=0; //写指令:RS=L,RW=L,D0~D7=指令码,E=高脉冲
PORTD=com; //写指令到液晶
delay(5);
e=1;
delay(5);
e=0;
}
void write_data(uchar dat)//LCD1602数据输入
{ TRISD=0;
e=0;
rw=0;
rs=1;//写数据:RS=H,RW=L,D0~D7=指令码,E=高脉冲
PORTD=dat;//写数据到液晶
delay(5);
e=1;
delay(5);
e=0;
}
void disp_init()
{
TRISD=0;//选择D端口为液晶屏数据的输入口
write_com(0x38);//液晶开显示
write_com(0x0c);//显示光标,光标闪烁write_com(0x06);//读或写一个字符后地址指针加一,光标加一
write_com(0x01);//显示清屏:1、数据指针清零;2、所有显示清零
write_com(0x80);//第一行首位
}
void disp(uchar num1,uchar num2,uchar num3)
{
write_com(0x80+0x40);
write_data(num1+0x30);//液晶第二行第一位数
delay(1);
write_com(0x80+0x41);
write_data(num2+0x30);//液晶第二行第二位数
delay(1);
write_com(0x80+0x42);
write_data(num3+0x30);//液晶第二行第三位数
delay(1);
}
void delay(uint z)//z毫秒延时子法式
{
uint x,y;
for(x=110;x>0;x--)
for(y=z;y>0;y--);
}
附录二(任务三法式)
#include <pic18.h> //调用头文件,可以去PICC18软件下去查找PIC18FXX2.H
__CONFIG(1,XT) ; //晶振为外部4M
__CONFIG(2,WDTDIS) ; //看门狗关闭
__CONFIG(4,LVPDIS) ; //禁止低电压编程
#define RSPIN RB5 //Data or Instrument Select LCD1602
#define RWPIN RB4 //Write or Read
#define EPIN RB3 //6800 mode Enable single
unsigned char temp1=0,temp1_1=0; //收集到的温度高8位上一次的
unsigned char temp2=0,temp2_2=0; //收集到的温度低8位
unsigned int a,b,c=0;
#define beep RC2 //界说蜂鸣器接口
/****************************************/
#define sda RC4 //AT24C02
#define scl RC3
bit eepromdi;
bit eepromdo;
unsigned char addressbuf;
unsigned char buf_24C02;
/****************************************/
bit clrbit; //USART
unsigned char recebuf;
/****************************************/
//转换后的温度值小数点部份查表
const unsigned char tablexiao[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};
/***************************************************************************** ***********/
#define Key_Data RB1
#define Key_CLK RB0
unsigned char IntNum; //中断次数计数
unsigned char KeyV; //键值
unsigned char Key_UP=0, Shift = 0;//Key_UP是键松开标识,Shift是Shift键按下标识unsigned char keybuf;
unsigned char disbuf;//84
unsigned char shu1=0,shu2=0,tem1=0,tem2=0,tem3=0; //温度上限
bit bf; //标识是否有字符被收到
bit disbit;
//0x66为backspace键
//0x5a为Enter键
const unsigned char UnShifted[59][2] = {
0x1C, 'a',
0x32, 'b',
0x21, 'c',
0x23, 'd',
0x24, 'e',
0x2B, 'f',
0x34, 'g',
0x33, 'h',
0x43, 'i',
0x3B, 'j',
0x42, 'k',
0x4B, 'l',
0x3A, 'm',
0x31, 'n',
0x44, 'o',
0x4D, 'p',
0x15, 'q',
0x2D, 'r',
0x1B, 's',
0x2C, 't',
0x3C, 'u',
0x2A, 'v',
0x1D, 'w',
0x22, 'x',
0x35, 'y',
0x1A, 'z',
0x45, '0',
0x16, '1',
0x1E, '2',
0x26, '3',
0x25, '4',
0x2E, '5',
0x36, '6',
0x3D, '7',
0x3E, '8',
0x46, '9',
0x0E, '`',
0x4E, '-',
0x55, '=',
0x5D, '\\',
0x29, ' ',
0x54, '[',
0x5B, ']',
0x4C, ';',
0x52, '\'',
0x41, ',',
0x49, '.',
0x4A, '/',
0x71, '.',
0x70, '0',
0x69, '1',
0x72, '2',
0x7A, '3',
0x6B, '4',
0x73, '5',
0x74, '6',
0x6C, '7',
0x75, '8',
0x7D, '9',
};
const unsigned char Shifted[59][2] = { 0x1C, 'A',
0x32, 'B',
0x21, 'C',
0x23, 'D',
0x24, 'E',
0x2B, 'F',
0x34, 'G',
0x33, 'H',
0x43, 'I',
0x3B, 'J',
0x42, 'K',
0x4B, 'L',
0x3A, 'M',
0x31, 'N',
0x44, 'O',
0x4D, 'P',
0x15, 'Q',
0x2D, 'R',
0x1B, 'S',
0x2C, 'T',
0x3C, 'U',
0x2A, 'V',
0x1D, 'W',
0x22, 'X',
0x35, 'Y',
0x1A, 'Z',
0x45, '0',
0x16, '1',
0x1E, '2',
0x26, '3',
0x25, '4',
0x2E, '5',
0x36, '6',
0x3D, '7',
0x3E, '8',
0x46, '9',
0x0E, '~',
0x4E, '_',
0x55, '+',
0x5D, '|',
0x29, ' ',
0x54, '{',
0x5B, '}',
0x4C, ':',
0x52, '"',
0x41, '<',
0x49, '>',
0x4A, '?',
0x71, '.',
0x70, '0',
0x69, '1',
0x72, '2',
0x7A, '3',
0x6B, '4',
0x73, '5',
0x74, '6',
0x6C, '7',
0x75, '8',
0x7D, '9',
};
//******************************************************************/ //6x8.h文件:
/*-----------------------------------------------
6 x 8 font
1 pixel space at left and bottom
index = ASCII - 32
-----------------------------------------------*/
const unsigned char font6x8[][6] =
{
{ 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },// ! { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },// " { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },// # { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 },// $ { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 },// %5 { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 },// & { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 },// ' { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 },// ( { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 },// ) { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 },// * { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 },// + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 },// , { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 },// - { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },// . { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 },// / { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E },// 0 16 { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 },// 1 { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 },// 2 { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 },// 3 { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 },// 4 { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 },// 5 { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 },// 6 { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 },// 7 { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 },// 8 { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E },// 9 { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 },// : 26 { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 },// ; { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },// < { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 },// = { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 },// > { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 },// ? { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E },// @ { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C },// A33 { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 },// B { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 },// C { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C },// D { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 },// E { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 },// F { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A },// G { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F },// H { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 },// I { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 },// J { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 },// K { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 },// L { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F },// M { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F },// N { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E },// O { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 },// P { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E },// Q { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 },// R { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 },// S { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 },// T { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F },// U { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F },// V { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F },// W { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 },// X
{ 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 },// Z
{ 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 },// [59
{ 0x00, 0x02, 0x04, 0x08, 0x10, 0x20 },// '\'
{ 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 },// ]
{ 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 },// ^
{ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 },// _
{ 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 },// '
{ 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 },// a 65
{ 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 },// b
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 },// c
{ 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F },// d
{ 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 },// e
{ 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 },// f
{ 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C },// g
{ 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 },// h
{ 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 },// i
{ 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 },// j
{ 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 },// k
{ 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 },// l
{ 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 },// m
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 },// n
{ 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 },// o
{ 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 },// p
{ 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC },// q
{ 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 },// r
{ 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 },// s
{ 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 },// t
{ 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C },// u
{ 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C },// v
{ 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C },// w
{ 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 },// x
{ 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C },// y
{ 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 },// z 90
{ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 },// | 91
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }// horiz lines
};
/***************************************************************************** **************************/
void delay(unsigned char x,unsigned char y)
{
unsigned char z;
do{
z=y;
do{
;
}while(--z);
}while(--x);
}
//名称: 复位DS18B20函数
unsigned char reset(void)
{
unsigned char 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(unsigned char val)
{
unsigned char i;
unsigned char temp;
for(i=8;i>0;i--)
{
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; //右移一位
}
}
//名称: 读字节函数
unsigned char read_byte(void)
{
unsigned char i;
unsigned char value=0; //读出温度
for(i=8;i>0;i--)
{
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)
{
unsigned char 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 delay1(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++)
{
for(j=0;j<10;j++);
}
}
//名称: 1602忙检测函数
void lcd_wait_busy(void)
{
TRISD7=1; //为读状态做准备,把RD7设为输入
RSPIN=0; //选择指令寄存器
RWPIN=1; //选择读
EPIN=1; //使能线电平变动
while(RD7==1); //读忙状态,不忙时退出
EPIN=0; //恢复使能线电平
TRISD7=0; //把RD7设置为输出
}
//名称: 1602写命令函数
void lcd_write_com(unsigned char combuf)
{
RSPIN=0; //选择指令寄存器
RWPIN=0; //选择写
PORTD=combuf; //把命令字送入RD
EPIN=1; //使能线电平变动,命令送入1602的8位数据口asm("NOP"); //来一个空把持,以延时片刻
EPIN=0; //恢复使能线电平
}
//1602写命令函数(带忙检测)
void lcd_write_com_busy(unsigned char combuf)
{
lcd_wait_busy();//调用忙检测函数
lcd_write_com(combuf); //调用写命令函数
}
//1602写数据函数(带忙检测)
void lcd_write_data(unsigned char databuf)
{
lcd_wait_busy();//调用忙检测函数
RSPIN=1; //选择数据寄存器
RWPIN=0; //选择写
PORTD=databuf; //把数据字送入RD口
EPIN=1; //使能线电平变动,命令送入1602的8位数据口
asm("NOP");
EPIN=0; //恢复使能线电平
}
//名称: 1602显示地址写函数
void lcd_write_address(unsigned char x,unsigned char y)
{
x&=0x0f;//列地址限制在0-15
y&=0x01;//行地址限制在0-1
if(y==0x00)
lcd_write_com_busy(x|0x80); //第一行的列地址写入
else
lcd_write_com_busy((x+0x40)|0x80); //第二行的列地址写入
}
//名称: 1602初始化函数
void lcdreset(void)
{
delay1(150);
lcd_write_com(0x38);
delay1(50);
lcd_write_com(0x38);
delay1(50);
lcd_write_com(0x38);
lcd_write_com_busy(0x38); //8位数据,双列,5*7字形
lcd_write_com_busy(0x08);//显示功能关,无光标
lcd_write_com_busy(0x01);//清屏指令
lcd_write_com_busy(0x06);//写入新的数据后,光标右移,显示屏不移动
lcd_write_com_busy(0x0c);//显示功能开,无光标,
}
//指定地址写入函数
void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf)
{
lcd_write_address(x,y); //写入地址
lcd_write_data(buf);//写入显示数据
}
/*********************************************************************/ //T0初始化函数
void timer0init(void)
{
T0CS=0; //TMR0工作于按时器方式
PSA=1; //TMR0不分频
TMR0IF=0; //清除TMR0中断标识表记标帜
TMR0IE=1; //TMR0中断允许
T0CON=0x88; //16bit按时方式,预分频关闭,
TMR0H=(65536-50000)/256; //0.05;
TMR0L=(65536-50000)%256;
//GIE=1;
}
//T0中断函数 //外部中断INT处置函数 //PIC单片机和51单片机纷歧样,它只能有一个中断服务函数.
void interrupt ISR(void)
{
if(TMR0IF==1) //250us
{
//TMR0=0xff13; //晶振4.0M,按时250us
TMR0H=(65536-50000)/256; //0.05;
TMR0L=(65536-50000)%256;
TMR0IF=0;
a++;
if(a==20)
{
a=0;
b++;
if(b==999)
{
b=0;
}
c++;
}
}
if(INT0IF==1) //如果是外部中断
{
INT0IF=0; //清中断标识表记标帜位
if(IntNum==0) KeyV=0; //接收开始,将缓冲区清零
if((IntNum>0)&&(IntNum<9)) //接收8位有效码
{
KeyV=KeyV>>1; //因键盘数据是低>>高,结合上一句所以右移一位
if (Key_Data) KeyV=KeyV|0x80; //当键盘数据线为1时为1到最高位
}
IntNum++; //中断次数计次
if (IntNum > 10)
{
IntNum = 0; //傍边断11次后暗示一帧数据收完,清变量准备下一次接收
bf = 1; //接收完成标识表记标帜位,写1后,暗示接收OK
keybuf=KeyV; //把接收缓冲区的数据移植keybuf
KeyV=0; //接收缓冲区清0
}
}
}
/****************************************************************************/ /***************************************************************************/ //PS2解码处置函数
unsigned char Decode(unsigned char ScanCode)
//注意:如SHIFT+G为12H 34H F0H 34H F0H 12H?
//也就是说shift的通码+G的通码+shift的断码+G的断码
{
unsigned char TempCyc;
unsigned char KeyChar=0; if (!Key_UP) //当键盘松开时。