找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6485|回复: 4
打印 上一主题 下一主题
收起左侧

基于pcf8591的ad转换正弦波输出 带单片机源程序与仿真

[复制链接]
跳转到指定楼层
楼主
pcf8591是8位的ad转换器芯片,带da输出功能

用单片机定时器 定时输出数字量 转化成模拟电压 形成正弦波
运行后 在debug里面选择 digital oscillscope 调出示波器
通道a 幅值2mv  扫面速度2us
波形如下


单片机源程序如下:
  1. #include "reg51.h"
  2. #include "intrins.h"

  3. #define iic_delay() {_nop_();_nop_();_nop_();_nop_();}

  4. sbit scl = P1^6;
  5. sbit sda = P1^7;
  6. sbit led1 = P1^2;
  7. sbit led2 = P1^3;

  8. bit ack1 ,ack2;
  9. unsigned char d;

  10. void delayms(unsigned int x)
  11. {
  12.   unsigned int j;
  13.   while(x--)
  14.   for(j=125;j>0;j--);

  15. }
  16. void iic_start()
  17. {   
  18.    sda = 1;
  19.    scl = 1;

  20.    iic_delay();
  21.    sda = 0;
  22.    iic_delay();
  23.    scl = 0;

  24. }

  25. void iic_end()
  26. {
  27.    scl = 0;
  28.    sda = 0;
  29.    iic_delay();
  30.    scl = 1;
  31.    iic_delay();
  32.    sda = 1;
  33.    iic_delay();

  34. }

  35. bit iic_write(unsigned char dat)
  36. {        static bit ack;       
  37.         unsigned char mask;
  38.         for(mask=0x80;mask!=0;mask>>=1 )
  39.         {
  40.                  if((mask&dat)==0x00)
  41.                    sda = 0;
  42.                 else sda = 1;

  43.                   iic_delay();
  44.                    scl = 1;
  45.                    iic_delay();
  46.               scl = 0;
  47.         }

  48.         sda = 1;                                   //主机释放         开漏结构 写1的话 这个从机释放 当所有从机都写1的时候 总线才释放
  49.            iic_delay();                        //一旦某个从机写零 总线拉低 代表busy  见ti文档 2面
  50.         scl = 1;                                // 拉高 8+1  最后一个脉冲用于从机应答信号 scl 拉高 从机改变sda来响应是否应答
  51.         ack = sda;                            //scl拉低  主机sda 传输数据
  52.         iic_delay();
  53.         scl = 0 ;
  54.         return ack;
  55. }

  56. unsigned char iic_readdat_ack()
  57. {        static unsigned char mask,dat;
  58.         sda = 1;
  59.         for(mask = 0x80;mask!=0 ;mask>>=1)
  60.         {
  61.                          
  62.            iic_delay();                        //一旦某个从机写零 总线拉低 代表busy  见ti文档 2面
  63.         scl = 1;                                // 拉高 8+1  最后一个脉冲用于从机应答信号 scl 拉高 从机改变sda来响应是否应答
  64.         if(sda == 0)
  65.                 dat&=~mask;
  66.         else dat |= mask;

  67.            iic_delay();
  68.         scl = 0;

  69.         }
  70.         sda = 0;
  71.         iic_delay();
  72.         scl = 1;
  73.         iic_delay();
  74.         scl = 0;

  75.         return dat;

  76. }

  77. unsigned char iic_readdat_nack()
  78. {        static unsigned char mask,dat;
  79.         sda = 1;
  80.         for(mask = 0x80;mask!=0 ;mask>>=1)
  81.         {
  82.                          
  83.            iic_delay();                        //一旦某个从机写零 总线拉低 代表busy  见ti文档 2面
  84.         scl = 1;                                // 拉高 8+1  最后一个脉冲用于从机应答信号 scl 拉高 从机改变sda来响应是否应答
  85.         if(sda == 0)
  86.                 dat&=~mask;
  87.         else dat |= mask;

  88.            iic_delay();
  89.         scl = 0;

  90.         }
  91.         sda = 1;
  92.         iic_delay();
  93.         scl = 1;
  94.         iic_delay();
  95.         scl = 0;

  96.         return dat;

  97. }

  98. void sentad_data( char d )
  99. {
  100. iic_start();                     
  101.     ack1 = iic_write(0x48<<1);
  102.         led1 = ack1;
  103.         ack2 = iic_write(0x40);
  104.         led2 = ack2;

  105. //        iic_start();
  106. //        iic_write((0x48<<1)|0x01);
  107. //        iic_readdat_ack();
  108. //        d =   iic_readdat_nack();
  109. //        P3 = d;

  110.         iic_write(d);
  111.                           
  112.         iic_end();
  113. }
复制代码
  1. #include "reg51.h"
  2. #include "intrins.h"
  3. #include<math.h>

  4. #define time_step 15000                          //        定时器时常

  5. unsigned char DSY_BUFF_CODE[16] = {0xc0,0xf9,0xa4,0xb0,
  6.                                         0x99,0x92,0x82,0xf8,
  7.                                         0x80,0x90,0x88,0x83,
  8.                                         0xc6,0xa1,0x86,0x8e};

  9. sbit seg1 = P2^4;
  10. sbit seg2 = P2^5;
  11. sbit seg3 = P2^6;
  12. sbit seg4 = P2^7;

  13. void timer_init();
  14. void sentad_data(unsigned char);
  15. double  rad;


  16. void main()
  17. {

  18.           timer_init();
  19. //         sentad_data(0xff);                  
  20.     while(1);
  21. }

  22. void timer_init()
  23. {
  24.         TMOD=0x01;
  25.         TH0=(65536-time_step)/256;
  26.         TL0=(65536-time_step)%256;  
  27.         EA=1;
  28.         ET0=1;  
  29.         TR0=1;
  30. }


  31. void timer0_int() interrupt 1
  32. {        static unsigned char wei=0;
  33.         static  char d;
  34.         static unsigned int num = 0;                  //num 代表360个点中的第几个点  每次递增5个点
  35.        

  36.         TH0=(65536-time_step)/256;
  37.         TL0=(65536-time_step)%256;


  38.         d =(char)( (sin(0.01744*num))*127);          // 3.14115/180 表示每度的弧度值 乘以度数num
  39.         // 再把度数的sin值乘以127 输出成模拟电压量注意不能乘以255 因为这里是有符号类型 最高位是符号为 所以8位的数值最大位127
  40.                                                                                   
  41.         if((d&0x80)!=0x80)  d = d|0x80;                  //这里要再把最高位取反 与上0x80不等于0x80说明最高位为0 那么或上0x80将最高位置1
  42.         else d &= 0x7f;                                                  // 如果不将最高位取反的话 波形会有问题 见文件夹中的截图                         
  43.        
  44.         sentad_data(d);                                                  //将d输出成模拟电压

  45.         if(num==360) num =0;
  46.         num = num + 5;                                                  //每次递增5度

  47.          switch(wei)                                                  // 将d值送至数码管显示 可以通过调高time_step 观察d值 用于调试
  48.         {
  49.                  case 1:
  50.                 P2 &= 0x0f;
  51.                 P0 = DSY_BUFF_CODE[d/1000];
  52.                 seg1 = 1;
  53.                 break;

  54.                 case 2:
  55.                 P2 &= 0x0f;
  56.                 P0 = DSY_BUFF_CODE[d%1000/100];
  57.                 seg2 = 1;
  58.                 break;               

  59.                  case 3:
  60.                 P2 &= 0x0f;
  61.                 P0 = DSY_BUFF_CODE[d%100/10];
  62.                 seg3 = 1;
  63.                 break;

  64.                  case 4:
  65.                 P2 &= 0x0f;
  66.                 P0 = DSY_BUFF_CODE[d%10];
  67.                 seg4 = 1;

  68.                 break;

  69. ……………………

  70. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
1.zip (227.92 KB, 下载次数: 100)


评分

参与人数 2黑币 +55 收起 理由
18846934979 + 5 共享资料的黑币奖励!
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:490330 发表于 2019-4-2 20:25 | 只看该作者
很好,十分感谢
回复

使用道具 举报

板凳
ID:445096 发表于 2019-4-11 18:27 | 只看该作者
波形频率在哪里调
回复

使用道具 举报

地板
ID:445096 发表于 2019-4-11 20:43 | 只看该作者
972250229 发表于 2019-4-11 18:27
波形频率在哪里调

我也想问
回复

使用道具 举报

5#
ID:353450 发表于 2019-5-5 07:34 来自手机 | 只看该作者
TH0=(65536-time_step)/256;          TL0=(65536-time_step)%256;这句什么意思呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表