这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » blueapple2的DIY进程贴-按键扫描显示实验(视频)

共24条 3/3 1 2 3 跳转至
助工
2011-12-25 10:38:15     打赏
21楼
PCF8591AD实验:

助工
2011-12-25 10:39:46     打赏
22楼

代码:     //-----------------------函数声明,变量定义------------------------
#include <reg51.h>
#include <intrins.h>
sbit SCL=P1^1;                   // 将p1.2口模拟时钟口
sbit SDA=P1^2;                   // 将p1.3口模拟数据口
bit askflag;
#define uchar unsigned char
#define uint  unsigned int
#define disdata  P0              //显示数据码输出口

sbit LCD_RS = P2^4;             
sbit LCD_RW = P2^5;
sbit LCD_EN = P2^6;
#include <lcd.h>

uint data dis[4]={0x00,0x00,0x00,0x00}; 
                          //定义3个显示数据单元和1个数据存储单元

//uchar code dis4[] = {"1- .  V  2- .  V"};
//uchar code dis5[] = {"3- .  V  4- .  V"};


#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
                 
bit   bdata SystemError;                //从机错误标志位

/*********************** PCF8591专用变量定义 ***********************/

#define PCF8591_WRITE 0x90 
#define PCF8591_READ  0x91
#define  NUM  4              //接收和发送缓存区的深度
uchar idata receivebuf[NUM];    //数据接收缓冲区

/*******************************************************************/
/*                                                                 */
/*  延时函数                                                       */
/*                                                                 */
/*******************************************************************/

void delay(int ms)
{
    while(ms--)
{
      uchar i;
  for(i=0;i<250;i++)  
   {
    _nop_();    
_nop_();
_nop_();
_nop_();
   }
}
}

/*******************************************************************/
/*                                                                 */
/*检查LCD忙状态                                                    */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。      */
/*                                                                 */
/*******************************************************************/ 

bit lcd_busy()
 {                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result); 
 }

/******************************************************************/
/*                                                                */
/* 数据处理与显示                                                 */
/* 将采集到的数据进行16进制转换为ASCLL码。                        */
/*                                                                */
/******************************************************************/

void show_value(uchar ad_data)

{   
    dis[2]=ad_data/51;   //AD值转换为3为BCD码,最大为5.00V。
    dis[2]=dis[2]+0x30;  //转换为ACSII码
    dis[3]=ad_data%51;   //余数暂存
    dis[3]=dis[3]*10;    //计算小数第一位
    dis[1]=dis[3]/51;
    dis[1]=dis[1]+0x30;  //转换为ACSII码
    dis[3]=dis[3]%51;
    dis[3]=dis[3]*10;    //计算小数第二位
    dis[0]=dis[3]/51;                                                                             //
    dis[0]=dis[0]+0x30;  //转换为ACSII码           

//-------------------------------------------------------------------
// 函数名称: iic_start()
// 函数功能: 启动I2C总线子程序
//-------------------------------------------------------------------
void iic_start(void)
{ //时钟保持高,数据线从高到低一次跳变,I2C通信开始
SDA = 1;     
SCL = 1;
delayNOP();      // 延时5us 
    SDA = 0;
delayNOP();
    SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: iic_stop()
// 函数功能: 停止I2C总线数据传送子程序
//-------------------------------------------------------------------
void iic_stop(void)
{  
SDA = 0;       //时钟保持高,数据线从低到高一次跳变,I2C通信停止
SCL = 1;
delayNOP();
SDA = 1;
delayNOP();
    SCL = 0;
}
//------------------------------------------------------------------
// 函数名称: iicInit_()
// 函数功能: 初始化I2C总线子程序
//------------------------------------------------------------------
 void iicInit(void)
   {
   SCL = 0;
   iic_stop();
   }  
//-------------------------------------------------------------------
// 函数名称: slave_ACK
// 函数功能: 从机发送应答位子程序
//-------------------------------------------------------------------
void slave_ACK(void)
{
SDA = 0;  
SCL = 1;
delayNOP();
SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: slave_NOACK
// 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束
//-------------------------------------------------------------------
void slave_NOACK(void)

SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
    SCL = 0;  
}
//-------------------------------------------------------------------
// 函数名称: check_ACK
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
//-------------------------------------------------------------------
void check_ACK(void)
{      
    SDA = 1;        // 将p1.1设置成输入,必须先向端口写1
SCL = 1;
askflag = 0;
delayNOP();   
if(SDA == 1)    // 若SDA=1表明非应答,置位非应答标志askflag
    askflag = 1;
    SCL = 0;
}
//-------------------------------------------------------------------
// 函数名称: IICSendByte
// 入口参数: ch
// 函数功能: 发送一个字节
//-------------------------------------------------------------------
void IICSendByte(uchar ch)
 
{
   unsigned char idata n=8;     // 向SDA上发送一位数据字节,共八位

while(n--)

if((ch&0x80) == 0x80)    // 若要发送的数据最高位为1则发送位1
   {
  SDA = 1;    // 传送位1
SCL = 1;
    delayNOP();
// SDA = 0;
SCL = 0; 
   }
else
{  
SDA = 0;    // 否则传送位0
SCL = 1;
delayNOP();
   SCL = 0;
}
ch = ch<<1;    // 数据左移一位
}
}
//-------------------------------------------------------------------
// 函数名称: IICreceiveByte
// 返回接收的数据
// 函数功能: 接收一字节子程序
//-------------------------------------------------------------------
uchar IICreceiveByte(void)
{
uchar idata n=8;     // 从SDA线上读取一上数据字节,共八位
uchar tdata=0;
while(n--)
{
   SDA = 1;
   SCL = 1;
   tdata =tdata<<1;     //左移一位
    if(SDA == 1)
  tdata = tdata|0x01;   // 若接收到的位为1,则数据的最后一位置1
else 
  tdata = tdata&0xfe;   // 否则数据的最后一位置0
   SCL = 0;
 }

 return(tdata);
}
//-------------------------------------------------------------------
// 函数名称: DAC_PCF8591
// 入口参数: slave_add从机地址,n要发送的数据个数
// 函数功能: 发送n位数据子程序
//-------------------------------------------------------------------
void DAC_PCF8591(uchar controlbyte,uchar w_data)
{    

iic_start();                    // 启动I2C
delayNOP();

IICSendByte(PCF8591_WRITE);     // 发送地址位
check_ACK();                    // 检查应答位
    if(askflag == 1)
 { 
SystemError = 1;
return;                     // 若非应答,置错误标志位
     }
    IICSendByte(controlbyte&0x77); //Control byte 
check_ACK();                    //检查应答位
    if(askflag == 1)
 { 
SystemError = 1;
return;                    // 若非应答,置错误标志位
 }
    IICSendByte(w_data);        //data byte
check_ACK();                  // 检查应答位
    if(askflag == 1)
 { 
SystemError = 1;
     return;   // 若非应答表明器件错误或已坏,置错误标志位SystemError
 }
iic_stop();         // 全部发完则停止
delayNOP();
delayNOP();
delayNOP();
delayNOP();
}
//-------------------------------------------------------------------
// 函数名称: ADC_PCF8591
// 入口参数: controlbyte控制字
// 函数功能: 连续读入4路通道的A/D转换结果到receivebuf
//-------------------------------------------------------------------
void ADC_PCF8591(uchar controlbyte)

    uchar idata receive_da,i=0;
while(i<4)
{  

iic_start();

IICSendByte(PCF8591_WRITE); //控制字
check_ACK();
if(askflag == 1)
{
SystemError = 1;
return;
}

IICSendByte(controlbyte + i); //控制字
check_ACK();
if(askflag == 1)
{
SystemError = 1;
return;
}

    iic_start();                //重新发送开始命令
    IICSendByte(PCF8591_READ); //控制字
check_ACK();
if(askflag == 1)
{
SystemError = 1;
return;
}
 
    IICreceiveByte();   //空读一次,调整读顺序
    slave_ACK();        //收到一个字节后发送一个应答位

//while(i<4)
//{  
  receive_da=IICreceiveByte();
  receivebuf[i++]=receive_da;
  slave_ACK();       //收到一个字节后发送一个应答位
}
slave_NOACK();       //收到最后一个字节后发送一个非应答位
iic_stop();
}
//-------------------------------------------------------------------
// 函数名称: main
// 函数功能: 主程序
//-------------------------------------------------------------------
main()
{
    //uchar i,l;
 uchar l;
    delay(10);                 //延时
    LCD_init();                //初始化LCD             
  LCD_write_str(0,0,"1- .  V  2- .  V");
  LCD_write_str(1,0,"3- .  V  4- .  V");
  while(1)
  {

iicInit();               //I2C总线初始化
    ADC_PCF8591(0x04);

if(SystemError == 1)   //有错误,重新来
  {
   iicInit();   //I2C总线初始化
    ADC_PCF8591(0x04);
   }   

for(l=0;l<4;l++)
 {
        show_value(receivebuf[0]); //显示通道0       
        LCD_write_char(0,2,dis[2]);        //整数位显示
  LCD_write_char(0,3,'.');     //小数点
        LCD_write_char(0,4,dis[1]);        //第一位小数显示 
        LCD_write_char(0,5,dis[0]);        //第二位小数显示

        show_value(receivebuf[1]); //显示通道1  
        LCD_write_char(0,11,dis[2]);        //整数位显示
  LCD_write_char(0,12,'.');     //小数点
        LCD_write_char(0,13,dis[1]);        //第一位小数显示 
        LCD_write_char(0,14,dis[0]);        //第二位小数显示

        show_value(receivebuf[2]); //显示通道2           
        LCD_write_char(1,2,dis[2]);        //整数位显示
  LCD_write_char(1,3,'.');     //小数点
        LCD_write_char(1,4,dis[1]);        //第一位小数显示 
        LCD_write_char(1,5,dis[0]);        //第二位小数显示

        show_value(receivebuf[3]); //显示通道3  
        LCD_write_char(1,11,dis[2]);        //整数位显示
  LCD_write_char(1,12,'.');     //小数点
        LCD_write_char(1,13,dis[1]);        //第一位小数显示 
        LCD_write_char(1,14,dis[0]);        //第二位小数显示

      iicInit();               //I2C总线初始化  
      DAC_PCF8591(0x40,receivebuf[0]); //D/A输出

    if(SystemError == 1)   //有错误,重新来
    {
    iicInit();   //I2C总线初始化
 DAC_PCF8591(0x40,receivebuf[0]); //D/A输出
    }         

      //delay(50);                       //延时
 }

   }
}


助工
2011-12-25 10:41:44     打赏
23楼

LCD.h
/******************************************************
*MCU at89s52
*晶振 12MHz
*LCD1602 4位数据线程序
*   端口名称              端口符号     MCU端口    LCD引脚
*   RS数据/指令选择线        RS          P0^0       4    P2^4
*   R/W读写选择线            R/W         GND        5    P2^5
*   EN写使能线               EN          PD0^1      6    P2^6
*   数据总线                 D0-D3       NC        7-10
*                            D4          P1^4      11    P0^4
*                            D5          P1^5      12    P0^5
*                            D6          P1^6      13            P0^6
*                            D7          P1^7      14    P0^7
*   其他端口连接:
*                        电源负     VSS             1
*                        电源正+4.5--+5.5V   VDD    2
*                        对比度调节    VL  用1(10k左右电阻连接至地)  3
*                        背光负        BLK   VDD   15   
*                        背光正        BLA   GND   16
*********************************************************************************/

#define uint unsigned int
#define uchar unsigned char
//#define disdata P0
//sbit RS=P2^4;
//sbit RW=P2^5;
//sbit LCD_EN=P2^6;

void delay_nms(uint z)//毫秒级延时函数
 {
   uint i,j;
   for(i=0;i<z;i++)
   for(j=0;j<120;j++);
 }

void write_num(uchar num)     //写数据线命令(四线模式数据要分两次写)
   {
     disdata &= 0x0F;         //清高四位端口
     disdata |= (num&0xF0);   //写高四位数据
     delay_nms(2);     //小于 2ms出现少首字符现象
     LCD_EN = 1;              //EN=1
     LCD_EN = 0;             //EN=0
     disdata &= 0x0F;              //清高四位端口
     disdata |= ((num&0x0F)<<4);   //写低四位数据
     delay_nms(2);
     LCD_EN = 1;              //EN=1
     LCD_EN = 0;             //EN=0
 
   }

void write_com(uchar com)  //写指令
   {
    LCD_RS = 0;
  LCD_RW = 0;
    write_num(com);
   }
 
void write_dat(uchar dat)  //写函数
   {
    LCD_RS = 1;
 LCD_RW = 0;
    write_num(dat);
   }

void LCD_init(void)       //LCD初始化
   {
    delay_nms(15);         //原来1602初始化成4位数据线之前必需先初始化成8位
    write_com(0x33);       //(此时命令发送方式是8位格式,但数据线只需接4位),
    delay_nms(5);          //然后再改到4位线宽,这样初始化才稳定
    write_com(0x32);
    delay_nms(5);
    write_com(0x28);   //四线模式设置
    write_com(0x0f);   //显示开--对应开关显示控制指令
    write_com(0x01);   //清屏--对应清屏指令
    delay_nms(5);
   }

void LCD_pos(uchar x,uchar y)//写地址函数
   {
     if(x)
         write_com(0xc0+y); //第二行显示
     else
         write_com(0x80+y); //第一行显示
   }
 
void LCD_write_char(uchar x,uchar y,uchar zifu) //写字符函数
   {
      LCD_pos(x,y);
      write_dat(zifu);
   }
 
void LCD_write_str(uchar x,uchar y,uchar *s)//写字符串函数
   {
      LCD_pos(x,y);
      while(*s)
     {
         write_dat(*s);
         s++;
 
      }
    }

 


菜鸟
2012-01-28 14:47:17     打赏
24楼

共24条 3/3 1 2 3 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]