数模A/D和模数D/A转换的基本应用(下)

模拟技术

2414人已加入

描述

代码相关:

/**********Lcd1602.c**************/
#include < reg52.h >
#define LCD1602_DB  P2
sbit LCD1602_RS = P0^3;
sbit LCD1602_RW = P0^2;
sbit LCD1602_E  = P0^1;
void LcdWaitReady()
{
    unsigned char sta;  
    LCD1602_DB = 0xFF;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
        LCD1602_E = 1;
        sta = LCD1602_DB; //读取状态字
        LCD1602_E = 0;
    } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E  = 1;
    LCD1602_E  = 0;
}
void LcdSetCursor(unsigned char x, unsigned char y)
{
    unsigned char addr;

    if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
        addr = 0x00 + x;  //第一行字符地址从0x00起始
    else
        addr = 0x40 + x;  //第二行字符地址从0x40起始
    LcdWriteCmd(addr | 0x80);  //设置RAM地址
}


void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
    LcdSetCursor(x, y);   //设置起始地址
    while (*str != '�')  //连续写入字符串数据,直到检测到结束符
    {
        LcdWriteDat(*str++);
    }
}
/* 初始化1602液晶 */
void InitLcd1602()
{
    LcdWriteCmd(0x38);  
    LcdWriteCmd(0x0C);  
    LcdWriteCmd(0x06);  
    LcdWriteCmd(0x01);  
}
/*********************IIC*******************/
#include < reg52.h >
#include < intrins.h >
#define Delay()  {_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;


/* 起始信号 */
void I2CStart()
{
    I2C_SDA = 1; 
    I2C_SCL = 1;
    Delay();
    I2C_SDA = 0; 
    Delay();
    I2C_SCL = 0; 
}
/* 停止信号 */
void I2CStop()
{
    I2C_SCL = 0; //首先确保SDA、SCL都是低电平
    I2C_SDA = 0;
    Delay();
    I2C_SCL = 1; //先拉高SCL
    Delay();
    I2C_SDA = 1; //再拉高SDA
    Delay();
}
/* I2C总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit I2CWrite(unsigned char dat)
{
    bit ack;  
    unsigned char BitCnt;  


    for (BitCnt=0x80; BitCnt!=0; BitCnt > >=1) 
    {
        if ((BitCnt&dat) == 0)  
            I2C_SDA = 0;
        else
            I2C_SDA = 1;
        Delay();
        I2C_SCL = 1;          //拉高SCL
        Delay();
        I2C_SCL = 0;          //再拉低SCL,完成一个位周期
    }
    I2C_SDA = 1;  
    Delay();
    I2C_SCL = 1;   
    ack = I2C_SDA; 
    Delay();
    I2C_SCL = 0; 


    return (ack); 

}


/* I2C总线读操作,并发送应答信号或者非应答信号,如果cnt为1则发送应答信号,
如果cnt为非1的值则发送非应答信号,返回值-读到的字节 */
unsigned char I2CReadACKORNOT(bit cnt)
{
    unsigned char BitCnt;
    unsigned char dat;


    I2C_SDA = 1;  //首先确保主机释放SDA
    for (BitCnt=0x80; BitCnt!=0; BitCnt > >=1) //从高位到低位依次进行
    {
        Delay();
        I2C_SCL = 1;      //拉高SCL
        if(I2C_SDA == 0)  //读取SDA的值
            dat &= ~BitCnt; //为0时,dat中对应位清零
        else
            dat |= BitCnt;  //为1时,dat中对应位置1
        Delay();
        I2C_SCL = 0;      //再拉低SCL,以使从机发送出下一位
    }
    if(cnt)
    I2C_SDA = 0;   //8位数据发送完后,拉低SDA,发送应答信号
    else
    I2C_SDA = 1;
  Delay();
    I2C_SCL = 1;   //拉高SCL
    Delay();
    I2C_SCL = 0;   //再拉低SCL完成应答位,并保持住总线


    return dat;
}
/******************main.c*************************/
#include < reg52.h >
bit flags = 1;  
unsigned char GetValue(unsigned char chn);
void NumToString(unsigned char *str, unsigned char val);
extern void I2CStart();
extern void I2CStop();
unsigned char I2CReadACKORNOT(bit cnt);
extern bit I2CWrite(unsigned char dat);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);


void main()
{
    unsigned char val;
    unsigned char str[10];

    EA = 1;            //开总中断
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0为模式1
    TH0 = (65536-9216)/256;     //加载T0重载值,定时10ms
    TL0 = (65536-9216)%256;
    ET0 = 1;        //使能T0中断
    TR0 = 1;        //启动T0
    InitLcd1602();     //初始化液晶    
    LcdShowStr(0, 0, "AN0:  AN1:  AN3:");  //显示通道指示

    while (1)
    {
        if (flags)
        {
            flags = 0;
            //显示通道0的电压
            val = GetValue(0);     //获取ADC通道0的转换值
            NumToString(str, val);  //转为字符串格式的电压值
            LcdShowStr(0, 1, str);    //显示到液晶上
            //显示通道1的电压
            val = GetValue(1);
            NumToString(str, val);
            LcdShowStr(6, 1, str);
            //显示通道3的电压
            val = GetValue(3);
            NumToString(str, val);
            LcdShowStr(12, 1, str);
        }
    }
}
unsigned char GetValue(unsigned char chn)
{
  unsigned char val;


  I2CStart();
  if(I2CWrite(0x48< < 1))
  {
    I2CStop();
    return 0;
  }
  I2CWrite(0x40 | chn);
  I2CStart();
  I2CWrite(0x48< < 1 | 0x01);
  I2CReadACKORNOT(1);
  val = I2CReadACKORNOT(0);
  I2CStop();
  return val;
}


void  NumToString(unsigned char *str, unsigned char val)
{
  val = (val*50)/255;
  str[0] = (val/10) + '0';
  str[1] = '.';
  str[2] = (val%10) + '0';
  str[3] = '�';

}


/* T0中断服务函数 */
void InterruptTimer0() interrupt 1
{
    static unsigned char tm100ms = 0;

    TH0 = (65536-9216)/256;     //加载T0重载值
    TL0 = (65536-9216)%256;
    tm100ms++;
    if (tm100ms >= 10)  //定时100ms
    {
        tm100ms = 0;
        flags = 1;
    }
}

AN3通道测得实际电压变化,通过滑动变阻器可以改变相应的值;AN0通道测得光敏电阻的阻值;AN1测得热敏电阻的相应阻值,需要货源才会变化值。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分