|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
PCF8591 AD采集单片机程序 LCD1602显示
5 c( D9 b. W, ?8 J* n. l#include<reg52.h>
4 J6 b+ T: E7 f+ D: Y6 @5 D; Y- ]#include<intrins.h>' \5 a- Z+ r7 o) W+ h( c
#define uchar unsigned char% s1 v# U$ l+ Q# H0 d3 j1 a- z6 E
#define uint unsigned int
( D0 H, T' o' P( y i#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
& o+ s* \/ v8 m4 U! tsbit LCD_RS=P2^2;
- O/ ]' A: p# f: dsbit LCD_RW=P2^1;
1 h& I& R3 @( E: u% j: L- nsbit LCD_EN=P2^0;& Z4 F9 ~1 _" ?- w/ |
sbit SCL=P1^0; //I2C时钟引脚
* N" v5 T0 U5 p: \5 d3 O) a0 Osbit SDA=P1^1; //I2C数据输入输出引脚
/ _9 v/ X. {+ P; A. fuchar Recv_Buffer[4]; //数据接收缓冲& F \& z5 e8 r+ ?6 s R
uint Voltage[]={'0','0','0','0','0','0'}; //数据分解为电压x.xx. @0 j& Q8 e( R
bit bdata IIC_ERROR; //I2C错误标志位1 u6 m& a: a- c. V( B3 ^# N# V
uchar LCD_Line_1[]={"DQ . ppm "};0 U/ g N+ k7 g9 E2 H
//延时+ {: h4 ]7 T) F# ?# a
void delay(int ms)4 e! D$ j# {( p s: z: M
{
. i3 r& f8 v; x. @uchar i;4 u6 A. p+ b! x" e1 x! T
while(ms--) for(i=0;i<250;i++) Delay4us();
, P2 a H' F4 c- C" \}
* Z2 @4 v$ T$ y. T- F# E6 D//LCD忙检测 p# b% l V1 d
bit LCD_Busy_Check()
+ ?+ J% P7 z/ X) Y/ \2 o{
3 Z ^2 l2 E* x& Fbit Result;. Y% t! f4 Y- Y$ p
LCD_RS=0;LCD_RW=1;3 z) S8 y( R) f6 m% T2 J; U. I
LCD_EN=1;Delay4us();Result=(bit)(P0&0x80);
* h& K N7 ^ Q" z' j- | KLCD_EN=0;
& P4 x' T! X' B. V1 D' i# @return Result;0 t: Q$ X* W d0 C, a r
}
( q* j; J( Q% c7 y//写指令& j7 I1 `1 d2 }! |0 e
void LCD_Write_Command(uchar cmd)# o# o3 r2 c" @4 L
{
) m4 _5 _# s6 X" ^3 vwhile(LCD_Busy_Check());
4 k5 h. W) j; b: T4 q- XLCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();. e+ O' ]7 L% V5 m. a1 j1 g1 `
P0=cmd;Delay4us();
( D3 E- n! a# v$ z7 M; x0 I2 yLCD_EN=1;Delay4us();LCD_EN=0;3 [# W. {5 B8 }
}4 B8 J+ w4 T2 H
// 写数据; u' P' @3 B0 y
void LCD_Write_Data(uchar dat)
# C6 ?, ^+ P& C; h" K# g4 P+ K' ?{5 l2 U+ \5 J. N* `& a3 X' c
while(LCD_Busy_Check());
0 i' V/ m: s/ [" O2 o( iLCD_RS=1;LCD_RW=0;LCD_EN=0 0=dat;Delay4us();2 H6 \; E7 k9 ^' ~5 C7 S- X5 g
LCD_EN=1;Delay4us();LCD_EN=0;: t3 H5 Z" y+ w, B% D$ p, @* h
}* J' @: s, G; C/ [. v! P0 D7 v$ Q
//初始化# U/ v4 [5 D/ E: r/ R4 [
void LCD_Initialise()
" x8 ^" K1 V* \# q9 V5 [6 v0 A, d{) s X6 {/ S- I! r/ W
LCD_Write_Command(0x38);delay(5);
) K( ^- S! p5 C# _LCD_Write_Command(0x0c);delay(5);+ v! L+ W% `5 N
LCD_Write_Command(0x06);delay(5);
& N; c/ D4 u) ^& R8 h4 l. R9 ULCD_Write_Command(0x01);delay(5);
- R5 X j' E$ `8 \* s; V, ~* FLCD_Write_Command(0x03);delay(5);
5 Z* U) g# ~1 H- gLCD_Write_Command(0x02);delay(5);% z, @$ }, N# f8 d! Q
}8 v+ s6 C! u3 [/ y$ }7 k& \' j
//设置显示位置
+ j, l7 o8 b9 L! w$ xvoid LCD_Set_Position(uchar pos)
_6 D4 k- O5 b- k5 M; p{* C4 l& R0 Q# a. `& _
LCD_Write_Command(pos|0x80);$ B- g; A/ m* ~- l9 P& ~+ P# E9 s
}. ? c" ?0 |* ^" x2 W2 e7 Y
//显示一行4 C S& F# r% C9 M H, V4 W
void LCD_Display_A_Line(uchar Line_Addr,uchar s[])
" s8 A, r4 k2 u. C( I7 P0 x{
% y/ C* Z$ d' h" i; K0 p5 m2 F5 zuchar i;, b7 Z8 ^6 f5 j: K
LCD_Set_Position(Line_Addr);
7 `6 \5 e; Q2 R, e" d' Q6 b- @2 o1 m: ?for(i=0;i<16;i++)LCD_Write_Data(s);
2 v4 L; g' y0 D4 n; V* i: P1 V}
( n2 U8 `, B. n j* X8 Z% ^# T' A// 将模数转换后得到的值分解存入缓存
$ n' l; b$ ?# B" L7 {" V0 B& Pvoid Convert_To_Voltage(uchar val)
& S- g2 k E1 N' W6 F! W{ }4 ]' x4 o: @" p8 x
uchar Tmp; //最大值为255,对应5V
! O9 [) I% {' d; W+ oVoltage[2]=val/100+'0'; //整数部分
0 c" g2 a/ y, j: l& H2 K; \Voltage[3]=val/10%10+'0' ;
, ?* u6 g/ y: S# v8 l' t) t8 LVoltage[4]=val%10+'0' ;7 P$ e; a! u8 x, n; Y' D+ Y
Tmp=val*10; // 第一位小数! c+ x2 N! e1 B+ m" N
Voltage[1]=Tmp%10+'0';
$ W1 {, ~/ w8 C4 n: o" ~3 \Tmp=Tmp*10;
1 k8 V: p. p7 u1 B1 K* q7 aVoltage[0]=Tmp%10+'0';. U) c' ]' D/ j
}) u2 X. O( B. v* _3 x
//启动I2C总线1 I% g- O0 a4 n6 m( o1 J i" W |
void IIC_Start()
* H: q( v: f+ N6 y4 S5 j+ M{& N* u2 e" h# J
SDA=1;SCL=1;Delay4us();SDA=0;Delay4us();SCL=0;
& R8 L$ W' z, i- ?& j- H. |}
$ r- \6 u8 p/ w2 ~- M9 b5 l/ G//停止I2C总线 A9 D9 P6 V2 }$ ?/ k% y
void IIC_Stop()
: P0 F: E, o6 ~5 l) T{
6 h" R6 @" n! b5 P9 ~5 aSDA=0;SCL=1;Delay4us();SDA=1; Delay4us();SCL=0;1 ^3 N. K. l) J! y/ [
}3 ]# R- L9 w. Y% z5 c
// 从机发送应答位
2 A! v! M9 l$ ^ _# ~- N- Yvoid Slave_ACK()8 }' @3 N0 |. N9 c; r
{
: M4 h5 ?: o/ r' ISDA=0;SCL=1;Delay4us();SCL=0;SDA=1;
+ H/ j# K- U" ^5 A}! b4 I& d6 ~7 n$ v9 z
// 从机发送非应答位- Q8 l. T/ c. t4 O
void Slave_NOACK()+ K7 d4 ?& c# P G: Y& _6 X$ e) Q1 S" i
{
. S9 ~, ]9 ?% l6 }SDA=1;SCL=1;Delay4us();SCL=0;SDA=0;
, V% T# Z* c8 O8 x* h& a% Q}) H8 B+ r9 N: w' P, ~3 w
//发送一字节" y' A0 X: ?# O4 {5 E
void IIC_SendByte(uchar wd)
/ ^, h0 k' ~! X( b9 b{
% |/ e7 [2 Z, N( H' c' [ huchar i;6 v# d2 R! Z. h
for(i=0;i<8;i++) //循环移入8位
4 W6 N' i% y- `1 s# Q% y{/ G: b% c$ |- u9 H. w' u' Z
SDA=(bit)(wd&0x80);_nop_();_nop_();
/ \9 ^: P# s2 B3 P$ U9 nSCL=1;Delay4us();SCL=0;wd<<=1;
9 E/ ]& ~' z: ]$ L5 \}
/ Z* o) p6 K+ b* j) f# O; Z+ n* o+ h9 gDelay4us();5 X' {! B' J% X0 i, k
SDA=1; //释放总线并准备读取应答: b) C# j8 E) `6 s
SCL=1;
( {. `" q. m5 ~6 G }- \4 }Delay4us();
3 Z- h: Z* A8 S5 U+ y0 h) HIIC_ERROR=SDA; //IIC_ERROR=1表示无应答
" ^/ J. ^2 G* ?3 c. MSCL=0; s- ~+ \3 L8 ~
Delay4us();8 f- j7 q: N& m
}1 V4 @0 T! p: C7 S& _6 d4 w
//接收一字节
0 K/ b+ f' \4 P: p" [7 `5 z( Wuchar IIC_ReceiveByte()1 R9 H7 W. r5 f: J/ L: j
{
0 E& v" Z4 b3 z9 X1 N1 d$ muchar i,rd=0x00;4 }/ H5 B. d. E$ [+ p
for(i=0;i<8;i++)$ M* k2 G o" Z5 A" `* z
{
% |. R1 l q' M8 M0 x' B, i5 |! S7 X$ mSCL=1;rd<<=1;rd|=SDA;Delay4us();SCL=0;Delay4us();
2 |$ o5 S5 ?0 @}' n; L. K( Y4 B% Q! R F7 a @5 m' O
SCL=0;Delay4us();
7 K1 e1 M: @8 ~6 x1 B& i( g+ ireturn rd;
' O. X" j4 f% I; f; f1 r0 ~+ p}. K" X k5 P* P0 s
//连续读入4路通道的A/D转换结果并保存到Recv_Buffer
) x7 r! x' u# N: xvoid ADC_PCF8591(uchar CtrlByte)
( ?$ o( d8 m3 B{* V' O( W: n/ I' ?: O+ x
uchar i;$ D9 B/ Y% N9 M) |9 {8 ~6 \7 N
IIC_Start();
$ h: q1 @1 B5 j: n1 [& V$ |( BIIC_SendByte(0x90); // 发送写地址1 t' C! A) z7 o2 [ I# q+ W# C. ^8 x
if(IIC_ERROR==1)return;' C) g; L7 @2 J+ |! Q
// IIC_SendByte(CtrlByte); //发送控制字节" ~: {8 Q8 R+ P. I
//if(IIC_ERROR==1)return;, {4 I( F- u4 p( ^
IIC_Start(); //重新发送开始命令
7 O8 q! M+ A0 pIIC_SendByte(0x91); // 发送读地址
/ p; J- I# C- I, w" E Vif(IIC_ERROR==1)return;
1 Q+ z9 f. ?0 Z- N3 J1 n7 n- v6 o1 xIIC_ReceiveByte(); //空读一次,调整读顺序$ K) G8 d* q3 v1 I/ W% K
Slave_ACK(); //收到一字节后发送一个应答位
0 c$ `6 d. L7 P+ \% e- _1 }# gfor(i=0;i<4;i++) k7 e9 T/ d6 e6 N
{
x- J/ e$ t/ F2 {Recv_Buffer[i++]=IIC_ReceiveByte();
; Y/ _) j: ]3 W% @Slave_ACK(); //收到一个字节后发送一个应答位
P& z; @9 d$ M# d}
8 h" a t0 D% H9 s0 d; @ z [5 iSlave_NOACK();
( d' l; k6 S2 b) XIIC_Stop(); //收到一个字节后发送一个非应答位
% t4 W3 s( o! R' P; O}
( x3 r m2 N! t [; }
/ W1 C% v* k# C1 L0 v3 m( [4 x Z$ t1 u# K! Z9 H$ q
…………限于本文篇幅 余下代码请从论坛下载附件…………
; l$ m! c% a+ e z t4 r/ ?% G2 t9 H6 E( v
J% f; t5 G& m0 G J
6 b O a. q6 j; @5 n- K |
|