|
想用PCF8591進(jìn)行AD轉(zhuǎn)換并將轉(zhuǎn)換的數(shù)傳入到單片機(jī)中,顯示在LCD1602液晶屏上,但是并不能得到數(shù)據(jù),顯示也不能進(jìn)行,顯示情況即為在初始位置不斷閃爍。本人大學(xué)生,想用單片機(jī)做一個(gè)散射式濁度計(jì),因此需要將檢測的光強(qiáng)顯示在液晶上,但無奈因?yàn)橹安⑽唇佑|過單片機(jī),所以一直找不到頭緒到底錯(cuò)在了哪里,還請各位大神指教。下面附上代碼,代碼也是我東拼西湊的,因?yàn)樽罱容^著急這個(gè)事,請問大家對如何寫有什么好建議嗎,是一邊模仿一邊學(xué)習(xí)還是如何呢。
#ifndef _I2C_H_
#define _I2C_H_
extern bit ack;
//起動(dòng)總線函數(shù)
extern void Start_I2c();
//結(jié)束總線函數(shù)
extern void Stop_I2c();
//應(yīng)答子函數(shù)
extern void Ack_I2c(bit a);
//字節(jié)數(shù)據(jù)發(fā)送函數(shù)
extern void SendByte(unsigned char c);
//有子地址發(fā)送多字節(jié)數(shù)據(jù)函數(shù)
extern bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) ;
//無子地址發(fā)送多字節(jié)數(shù)據(jù)函數(shù)
extern bit ISendStrExt(unsigned char sla,unsigned char *s,unsigned char no);
//無子地址讀字節(jié)數(shù)據(jù)函數(shù)
extern unsigned char RcvByte();
#endif
/*************************此部分為I2C總線的驅(qū)動(dòng)程序*************************************/
#include <reg52.h>
#include <intrins.h>
#include <I2C.H>
#define NOP() _nop_() /* 定義空指令 */
#define _Nop() _nop_() /*定義空指令*/
sbit SCL=P2^1; //I2C 時(shí)鐘
sbit SDA=P2^0; //I2C 數(shù)據(jù)
bit ack; /*應(yīng)答標(biāo)志位*/
/*******************************************************************
起動(dòng)總線函數(shù)
函數(shù)原型: void Start_I2c();
功能: 啟動(dòng)I2C總線,即發(fā)送I2C起始條件.
********************************************************************/
void Start_I2c()
{
SDA=1; /*發(fā)送起始條件的數(shù)據(jù)信號*/
_Nop();
SCL=1;
_Nop(); /*起始條件建立時(shí)間大于4.7us,延時(shí)*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*發(fā)送起始信號*/
_Nop(); /* 起始條件鎖定時(shí)間大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */
_Nop();
_Nop();
}
/*******************************************************************
結(jié)束總線函數(shù)
函數(shù)原型: void Stop_I2c();
功能: 結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件.
********************************************************************/
void Stop_I2c()
{
SDA=0; /*發(fā)送結(jié)束條件的數(shù)據(jù)信號*/
_Nop(); /*發(fā)送結(jié)束條件的時(shí)鐘信號*/
SCL=1; /*結(jié)束條件建立時(shí)間大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; /*發(fā)送I2C總線結(jié)束信號*/
_Nop();
_Nop();
_Nop();
_Nop();
}
/*******************************************************************
字節(jié)數(shù)據(jù)發(fā)送函數(shù)
函數(shù)原型: void SendByte(UCHAR c);
功能: 將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對
此狀態(tài)位進(jìn)行操作.(不應(yīng)答或非應(yīng)答都使ack=0)
發(fā)送數(shù)據(jù)正常,ack=1; ack=0表示被控器無應(yīng)答或損壞。
********************************************************************/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要傳送的數(shù)據(jù)長度為8位*/
{
if((c<<BitCnt)&0x80)SDA=1; /*判斷發(fā)送位*/
else SDA=0;
_Nop();
SCL=1; /*置時(shí)鐘線為高,通知被控器開始接收數(shù)據(jù)位*/
_Nop();
_Nop(); /*保證時(shí)鐘高電平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; /*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; /*判斷是否接收到應(yīng)答信號*/
SCL=0;
_Nop();
_Nop();
}
/*******************************************************************
字節(jié)數(shù)據(jù)接收函數(shù)
函數(shù)原型: UCHAR RcvByte();
功能: 用來接收從器件傳來的數(shù)據(jù),并判斷總線錯(cuò)誤(不發(fā)應(yīng)答信號),
發(fā)完后請用應(yīng)答函數(shù)應(yīng)答從機(jī)。
********************************************************************/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA=1; /*置數(shù)據(jù)線為輸入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; /*置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位*/
_Nop();
_Nop(); /*時(shí)鐘低電平周期大于4.7μs*/
_Nop();
_Nop();
_Nop();
SCL=1; /*置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; /*讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 */
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
/********************************************************************
應(yīng)答子函數(shù)
函數(shù)原型: void Ack_I2c(bit a);
功能: 主控器進(jìn)行應(yīng)答信號(可以是應(yīng)答或非應(yīng)答信號,由位參數(shù)a決定)
********************************************************************/
void Ack_I2c(bit a)
{
if(a==0)SDA=0; /*在此發(fā)出應(yīng)答或非應(yīng)答信號 */
else SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*時(shí)鐘低電平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0; /*清時(shí)鐘線,鉗住I2C總線以便繼續(xù)接收*/
_Nop();
_Nop();
}
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
當(dāng)使用的是4位數(shù)據(jù)傳輸?shù)臅r(shí)候定義,
使用8位取消這個(gè)定義
**********************************/
//#define LCD1602_4PINS
/**********************************
包含頭文件
**********************************/
#include<reg52.h>
//---重定義關(guān)鍵詞---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定義
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
/**********************************
函數(shù)聲明
**********************************/
/*在51單片機(jī)12MHZ時(shí)鐘下的延時(shí)函數(shù)*/
void Lcd1602_Delay1ms(uint c); //誤差 0us
/*LCD1602寫入8位命令子函數(shù)*/
void LcdWriteCom(uchar com);
/*LCD1602寫入8位數(shù)據(jù)子函數(shù)*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit();
#endif
#include"lcd.h"
/*******************************************************************************
* 函 數(shù) 名 : Lcd1602_Delay1ms
* 函數(shù)功能 : 延時(shí)函數(shù),延時(shí)1ms
* 輸 入 : c
* 輸 出 : 無
* 說 名 : 該函數(shù)是在12MHZ晶振下,12分頻單片機(jī)的延時(shí)。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //誤差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 數(shù) 名 : LcdWriteCom
* 函數(shù)功能 : 向LCD寫入一個(gè)字節(jié)的命令
* 輸 入 : com
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS //當(dāng)沒有定義這個(gè)LCD1602_4PINS時(shí)
void LcdWriteCom(uchar com) //寫入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //選擇發(fā)送命令
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待數(shù)據(jù)穩(wěn)定
LCD1602_E = 1; //寫入時(shí)序
Lcd1602_Delay1ms(5); //保持時(shí)間
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //寫入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //選擇寫入命令
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = com; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時(shí)序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
// Lcd1602_Delay1ms(1);
LCD1602_DATAPINS = com << 4; //發(fā)送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時(shí)序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數(shù) 名 : LcdWriteData
* 函數(shù)功能 : 向LCD寫入一個(gè)字節(jié)的數(shù)據(jù)
* 輸 入 : dat
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //寫入數(shù)據(jù)
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //選擇輸入數(shù)據(jù)
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //寫入數(shù)據(jù)
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時(shí)序
Lcd1602_Delay1ms(5); //保持時(shí)間
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //寫入數(shù)據(jù)
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //選擇寫入數(shù)據(jù)
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時(shí)序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //寫入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時(shí)序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數(shù) 名 : LcdInit()
* 函數(shù)功能 : 初始化LCD屏
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //開顯示
LcdWriteCom(0x0c); //開顯示不顯示光標(biāo)
LcdWriteCom(0x06); //寫一個(gè)指針加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設(shè)置數(shù)據(jù)指針起點(diǎn)
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //將8位總線轉(zhuǎn)為4位總線
LcdWriteCom(0x28); //在四位線下的初始化
LcdWriteCom(0x0c); //開顯示不顯示光標(biāo)
LcdWriteCom(0x06); //寫一個(gè)指針加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設(shè)置數(shù)據(jù)指針起點(diǎn)
}
#endif
#include "reg52.h"
#include "lcd.h"
#include "I2C.h"
typedef unsigned int u16;
typedef unsigned char u8;
#define READADDR 0x91;
#define WRITEADDR 0x90;
u8 hehe[5]="nihao";
void delay(u16 i)
{
while(i--);
}
void Pcf8591SendByte(uchar channel)
{
Start_I2c();
SendByte(0x91);
SendByte(0x40|channel);
Stop_I2c();
}
u8 Pcf8591ReadByte()
{
uchar num;
Start_I2c();
SendByte(0x90); //???????
num = RcvByte(); //????
Stop_I2c(); //????
return num;
}
void main()
{
u16 i,dat;
u8 dat;
Pcf8591SendByte(0x40);
dat=Pcf8591ReadByte();
LcdInit();
LcdWriteCom(0x80);
LcdWriteData(dat);
}
還請各位大神指教,有償也行的,是真的想了解到底為什么錯(cuò)了,錯(cuò)在哪里,我有什么做的不對的地方請各位大神指教。
全部資料51hei下載地址:
LCD顯示AD轉(zhuǎn)換結(jié)果.rar
(17.08 KB, 下載次數(shù): 13)
2019-4-17 09:02 上傳
點(diǎn)擊文件名下載附件
|
|