首页 > 其他分享 >PCF8591 AD/DA转换基于51

PCF8591 AD/DA转换基于51

时间:2023-04-22 09:14:17浏览次数:39  
标签:SCL AD delay3us void 51 unsigned DA char SDA

#include <reg52.h>
#include<intrins.h>    //内部有_nop_();
//IIC模拟时序实现
//注意:SCL为高电平时变化SDA数据是起始或者终止信号;所以若不是起始或者终止信号,需要在SCL为低电平时变化SDA数据

sbit SDA = P2^0;
sbit SCL = P2^1;
sbit LED = P2^3;
sbit wei = P2^6;
sbit duan = P2^7;

unsigned char num = 0;

unsigned char TEMP=0,flag=0;
unsigned char code table[] = "i get value: --" ;


unsigned char code duan_table[] = {0x3F, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};






//void delay(unsigned char t)
//{
//    unsigned char i,j;
//    for(i = t; i > 0; i --)
//    for(j = 110; j > 0; j --);
//}
void T1_Init()
{
    EA = 1;//打开总中断
//    ET1 = 1;//T1定时器中断打开    ,不屏蔽掉串口会一直发 ,像flag==1里出不来了
    TMOD = 0x20;//8位初值自动重装
    TH1 = 0xfd;
    TL1 = 0xfd;
    TR1 = 1; //启动定时器
    

}

void SCON_Init()
{
    SM0 = 0;
    SM1 = 1;//10bit

    REN = 1;//允许串行口接收数据
    ES = 1;
}





void delay3us()
{
    _nop_();    
    _nop_();
    _nop_();
}

void delayms(unsigned int t)
{
     unsigned int i,j;
    for(i = t; i > 0; i --)
    {
        for(j = 250; j > 0; j --);
    }
}

 
void start()
{
        
    SDA = 1;//scl=1写在SDA=1后面
    delay3us();
    delay3us();
    SCL = 1;////scl=1写在SDA=1后面,若是不这么做的话,万一SDA=1之前SDA是0就变成命令信号了
    delay3us();//SCL = 1需延时至少4.7us
    delay3us();
    
    SDA = 0;
    delay3us();//SDA = 0;SCL = 1需延时至少4us
    delay3us();

    SCL = 0;//释放SCL
    delay3us();
}

void stop()
{
     
     SDA = 0;
     delay3us();
     delay3us();

     SCL = 1;
     delay3us();//SCL = 1;SDA = 0需要至少延时4.7us
     delay3us();

     SDA = 1;
     delay3us();//SCL = 1;SDA = 1需要至少延时4.7us
     delay3us();

//     SDA = 0;    //这一句如果写了就是在SCL=1时变化了SDA

}  







 
void ack()
{
    SCL = 0;
    SDA = 1;
    delay3us();

    SDA = 0;  //SDA先清零,让SCL = 1,等最少4us,看SDA数据线是否被接收设备拉低了,拉低表示接收设备应答了
    delay3us();//如果不写上面的SDA = 0;万一是SDA = 1,下面SCL = 1,之后等待SDA被接收设备拉低,会出现,SCL=1时SDA拉低了,变成了起始信号了

    SCL = 1; //SCL=1,等接收设备拉低SDA表示应答
    delay3us();
    delay3us();

    SCL = 0;//释放总线
    delay3us();
    delay3us();
    SDA = 1;//[可写可不写该句X]必须要写,这里不明白
}


void noack()
{
    SCL = 0;
    SDA = 0;
    delay3us();

    SDA = 1;
    delay3us();

    SCL = 1;
    delay3us();
    delay3us();

    SCL = 0;//释放总线
    delay3us();
    delay3us();
    SDA = 0;//可写可不写
}  







//字节写入
void write_byte(unsigned char byte)
{
    unsigned char tmp_i,tmp_byte;    
    tmp_byte = byte;

    //启动信号发出后,便发出控制字,看start函数里SDA,SCL最后状态下笔
    for(tmp_i = 0; tmp_i < 8; tmp_i ++)
    {
        SCL = 0;//START函数里末尾也是SCL=0,应该可以不用写,但是循环所以建议写

        //scl=0 时可以变化SDA数据
        tmp_byte <<= 1;//高位先移,移出数据会进入PSW寄存器CY内
//        delay3us();
        SDA = CY;
        delay3us();

        SCL = 1;//数据停止变化,并保持一段时间
        delay3us();
        delay3us();


    }
    SCL = 0;//释放总线
    
    delay3us();
}
//字节读取
unsigned char read_byte()
{
    unsigned char i,byte;
    for(i = 0; i < 8; i ++)
    {
        SCL = 0;  //应答之后读取数据,看ack内部最后SDA,SCL状态
        byte <<= 1;//高位先移出,高位就先移入。ack函数内部,SCL是低电平的,这里循环所以再写一下
//        delay3us();
        byte |= SDA; //scl = 0从SDA获取数据,这里处理可能需要延时,防止时间太短
        delay3us();

        SCL = 1;   //数据停止变化,并保持一段时间
        delay3us();
        delay3us();
//        byte |= SDA;  //SCL为高并延时了至少4.7us,SDA稳定了,再处理数据亦可

    }

    SCL = 0;//释放总线
    delay3us();
    return byte;
}
//unsigned char read_byte()
//{
//    unsigned char i,byte;
//    for(i = 0; i < 8; i ++)
//    {
//        SCL = 1;   //数据停止变化,并保持一段时间
//        delay3us();
//        delay3us();
//        byte <<= 1;//高位先移出,高位就先移入。ack函数内部,SCL是低电平的,这里循环所以再写一下
//        byte |= SDA;  //SCL为高并延时了至少4.7us,SDA稳定了,再处理数据亦可
//
//        SCL = 0;  //应答之后读取数据,看ack内部最后SDA,SCL状态
//        delay3us();
////        byte |= SDA; //scl = 0从SDA获取数据,这里处理可能需要延时,防止时间太短
////        delay3us();
//
//        
//    }

//    SCL = 0;//释放总线
//    
//    delay3us();
//    return byte;
//}








//单字节写入数据到指定地址
void write_data(unsigned char add,unsigned char val)
{
    start();
    write_byte(0xae);
    ack();

    write_byte(add);
    ack();

    write_byte(val);
    ack();

    stop();
}
//单字节读取
unsigned char read_data(unsigned char add)
{
    unsigned char val=0;
    start();
    write_byte(0xae);
    ack();

    write_byte(add);
    ack();
    start();
    write_byte(0xaf);
    ack();

    val = read_byte();
    noack();

    stop();

    return val;
} 

//将数字值转换成模拟量输出函数
void DAC_convert(unsigned char val)
{
     start();
     write_byte(0x90);
     ack();

     write_byte(0x40);
     ack();

     write_byte(val);
     ack();

     stop();
//     write_byte(0x01);
//     ack();
}


//模数转换函数
unsigned char ADC_convert()
{
    
    unsigned char temp_val;


    start();
     write_byte(0x90);
     ack();

     write_byte(0x00);
     ack();




    start();
    write_byte(0x91);
    ack();

    temp_val = read_byte();
    ack();

    temp_val = read_byte();
    noack();

    stop();
    return temp_val;
}


void display()
{
    
    unsigned char numv=0;
    numv =     ADC_convert();

    wei = 1;
    P0 = 0xfe;
    wei = 0;

    duan = 1;
    P0 = duan_table[numv/100];

    duan = 0;

    delayms(1);

    P0 = 0XFF;

    wei = 1;
    P0 = 0xfd;
    wei = 0;

    duan = 1;
    P0 = duan_table[(numv%100)/10];

    duan = 0;

    delayms(1);

    P0 = 0XFF;

    wei = 1;
    P0 = 0xfb;
    wei = 0;

    duan = 1;
    P0 = duan_table[(numv%100)%10];

    duan = 0;

    delayms(1);

    P0 = 0XFF;


}



void main()
{
    

    T1_Init();
    SCON_Init();
    while(1)
    {
    
        display();
        
        if(flag == 1)
        {
            ES = 0;
            for(num = 0; num < 15; num ++)
            {
                SBUF = table[num];
                while(!TI);
                TI = 0;
            }
            SBUF = ADC_convert();
            while(!TI);
            TI = 0;

            flag = 0;
            ES = 1;
            
        }     
        
    }
        
        
}



void usart1() interrupt 4
{
    RI = 0;
//    TEMP = SBUF;//接收到数据存储到TEMP中
    flag = 1;
    
}

AD采样时序(类似):

并将转换发送到串口进行观察

 

标签:SCL,AD,delay3us,void,51,unsigned,DA,char,SDA
From: https://www.cnblogs.com/chillytao-suiyuan/p/17342408.html

相关文章

  • 为什么匿名内部类可以实例化并实现抽象方法?lambda表达式是简化了匿名内部类的实现过程
    为什么匿名内部类可以实例化并实现抽象方法?在Java中,接口是一种特殊的抽象类型,它只定义了一个或多个抽象方法。接口不能被实例化,但是我们可以使用匿名内部类来实现接口并创建一个具体的对象。匿名内部类是一种没有名字的局部内部类,它可以在定义的同时创建一个实例对象。因此,当我......
  • 58 openEuler搭建Mariadb数据库服务器-管理数据库
    58openEuler搭建Mariadb数据库服务器-管理数据库58.1创建数据库可以使用CREATEDATABASE语句来创建数据库。CREATEDATABASEdatabasename;其中:databasename为数据库名称,且数据库名称不区分大小写。例如示例命令如下:创建数据库名为testdb的数据库。MariaDB[(none)]>CRE......
  • day52 300.最长递增子序列 | 674. 最长连续递增序列 | 718. 最长重复子数组
    给你一个整数数组nums,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]是数组[0,3,1,6,2,2,7]的子序列。示例1:输入:nums=[10,9,2,5,3,7,101,18]输出:4解释:最长递增子序列是[2,3,7,101......
  • 数据对比DataCompare系统设计原理
    1背景介绍在日常数据研发工作中,我们会遇到如下常见场景问题,其一为:数据测试人员要对产出多表的一致性进行检测,其二为:数据对账体系,如资金流和订单数据要保持一致,其三为:数据模型迁移过程中,要对迁移前后的数据进行对比,其四为:数据存储在不同库中,例如A存储到ODPS,B存储到ADB,其中AB库中数据......
  • 2023-04-21:用go语言重写ffmpeg的metadata.c示例。
    2023-04-21:用go语言重写ffmpeg的metadata.c示例。答案2023-04-21:这段Go代码演示了如何使用ffmpeg-go库中的函数来读取多媒体文件元数据,包括视频、音频等信息。它的大体过程如下:设置环境变量以加载FFmpeg动态链接库这里将FFmpeg库中的各个动态链接库路径添加到环境变......
  • keras图片生成器ImageDataGenerator参数详解
    keras图片生成器ImageDataGeneratorkeras.preprocessing.image.ImageDataGenerator(featurewise_center=False,samplewise_center=False,featurewise_std_normalization=False,samplewise_std_normalization=False,zca_whitening=False,zca_epsilon=1e-......
  • k3s 基础 —— 配置 kubernetes-dashboard 的 token 过期时间
    拉取配置到本地:kubectlgetdeploykubernetes-dashboard-nkubernetes-dashboard-oyaml>dashboard-deploy.yaml增加参数:spec:containers:-args:---auto-generate-certificates---namespace=kubernetes-dashboard---to......
  • day04-商家查询缓存03
    功能02-商铺查询缓存033.功能02-商铺查询缓存3.6封装redis工具类3.6.1需求说明基于StringRedisTemplate封装一个工具列,满足下列需求:方法1:将任意Java对象序列化为json,并存储在string类型的key中,并且可以设置TTL过期时间方法2:将任意Java对象序列化为json,并存储在string类型的k......
  • boot-admin整合flowable官方editor-app源码进行BPMN2-0建模(续)
    boot-admin整合flowable官方editor-app源码进行BPMN2-0建模(续)书接上回项目源码仓库github项目源码仓库giteeboot-admin是一款采用前后端分离模式、基于SpringCloud微服务架构的SaaS后台管理框架。系统内置基础管理、权限管理、运行管理、定义管理、代码生成器和办公管理6个功......
  • 计网学习笔记九 Routing Fundamentals
    在这一讲开始讲路由器的控制平面。简单介绍了routing,两个最小cost算法。参考看的文章:VC网络中的路由VC网络和数据报网络中路由的区别:DifferencesbetweenVirtualCircuitsandDatagramNetworks三种路由方式(静态、默认和动态):TypesofRoutingRouting简介network对象不同......