全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 接口/总线/驱动 >

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

时间:2023-07-21 16:01

人气:

作者:admin

标签: 模数  数模      转换  基本 

导读:数模A/D和模数D/A转换的基本应用(下)-AN3通道测得实际电压变化,通过滑动变阻器可以改变相应的值;AN0通道测得光敏电阻的阻值;AN1测得热敏电阻的相应阻值,需要货源才会变化值。...

代码相关:

/**********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测得热敏电阻的相应阻值,需要货源才会变化值。

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信