找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2998|回复: 11
收起左侧

stc12单片机+AD7091R无法正常显示输入

[复制链接]
ID:947166 发表于 2021-7-12 09:45 | 显示全部楼层 |阅读模式
100黑币
各位大佬,我想用AD读取下电压,通过LCD显示,单片机用的STC12C5A60S2,20M外接晶振,1T的工作模式,AD用的AD7091R,这个AD是SPI的方式通信,但是写完程序调试不出结果,有没有输入都是显示4.99V,感觉是AD的DO引脚接的单片机引脚一直高电平的结果,AD貌似没有工作,AD前面接了AD820滤波,当有输入的时候测820输出和AD7091输入都是没问题的,麻烦各位大佬给看看程序有啥问题,感激不尽。
AD.PNG 这个图引脚不对,AD的几个引脚从上到下是3.2-3.5 引脚定义.png 时序.PNG
  1. </blockquote></div><div><div class="blockcode"><blockquote>#include "STC12C5A60S2.H"
  2. #include "tool.h"


  3. //ADC signal pin defination
  4. sbit ad_do = P3^2;
  5. sbit ad_cs = P3^3;
  6. sbit ad_cvt = P3^4;
  7. sbit ad_clk = P3^5;


  8. //ADC7091R Reset
  9. void adc_reset(void){
  10.         unsigned char i;
  11.         
  12.         ad_cvt = 0;        Delay1us();
  13.         ad_cvt = 1;        Delay1us();
  14.         ad_cs = 0;  Delay1us();
  15.         
  16.         
  17.         for(i=0;i<4;i++){
  18.                 ad_clk = 1; Delay1us();
  19.                 ad_clk = 0; Delay1us();               
  20.         }

  21.         ad_cs = 1;
  22.         ad_cvt = 0; Delay1us();
  23.         ad_cvt = 1;
  24.         
  25.         for(i=0;i<12;i++){
  26.                 ad_clk = 1; Delay1us();
  27.                 ad_clk = 0; Delay1us();
  28.         }


  29. }


  30. //ADC7091 Initialization
  31. void adc_init(void){
  32.   
  33.         ad_cvt = 1;
  34.   ad_cvt = 0;
  35.         ad_cvt = 1;Delay1us();
  36.   ad_cs  = 0;
  37.         
  38.         
  39. }

  40. //ADC7091 Converst progress
  41. uint adc_conv(void){
  42.   uchar i=0;
  43.         uint dat=0;
  44.   adc_init();

  45.   for(i=0; i<12; i++){
  46.                 ad_clk = 1;
  47.                
  48.                 dat <<= 1;Delay1us();
  49.                 if(ad_do) dat |= 0x0001;
  50.                 Delay1us();
  51.                 ad_clk = 0;Delay1us();
  52.                
  53.   }
  54.         
  55.   ad_cs = 1;
  56.         return dat;
  57. }
复制代码


主程序
  1. #include "adc7091.h"
  2. #include "IIC_1602.h"

  3. void Delay1000ms()                //@20.000MHz
  4. {
  5.         unsigned char i, j, k;

  6.         i = 76;
  7.         j = 255;
  8.         k = 241;
  9.         do
  10.         {
  11.                 do
  12.                 {
  13.                         while (--k);
  14.                 } while (--j);
  15.         } while (--i);
  16. }


  17. void main(){
  18.         //数据
  19.         uchar i=0;
  20.         uint ad_res;
  21.         uint ad_view = 0;
  22.         //IO口和LCD初始化
  23.         IO_Init();
  24.         init();
  25.         init_lcd();
  26.         adc_reset();
  27.         //adc_init();

  28.         while(1){
  29.                 ad_res = adc_conv();
  30.                
  31.                 ad_view = (ad_res*250.0/4095.0);
  32.                 bit_dis(ad_view);
  33.                 yuanshi(ad_res);
  34.                 ShowString(1,1,"V:");
  35.                 write_date(yuanshi_arr[3]);
  36.                 write_date(yuanshi_arr[2]);
  37.                 write_date(yuanshi_arr[1]);
  38.                 write_date(yuanshi_arr[0]);
  39.                
  40.                 ShowString(2,1,"Voltage:");
  41.                 write_date(res_arr[2]);
  42.                 write_date('.');
  43.                 write_date(res_arr[1]);
  44.                 write_date(res_arr[0]);

  45.                 //init_lcd();
  46.                 //Delay1000ms();Delay1000ms();
  47.         }
  48. }
复制代码




AD7091R_cn.pdf (1.25 MB, 下载次数: 4)

回复

使用道具 举报

ID:123289 发表于 2021-7-12 17:24 | 显示全部楼层
仔细读手册:
1、数据是串行工作的,每位数据的切换是需要时间的,切换位数(CLK)不要超过允许的时间。
2、数据切换后,要等数据稳定了再读取,要防止读到数据的边沿上。
3、AD转换需要时间,当下达开始转换之后,要确保转换已结束了,这时再读数据。
回复

使用道具 举报

ID:123289 发表于 2021-7-12 17:26 | 显示全部楼层
以上你做到了吗?
回复

使用道具 举报

ID:947166 发表于 2021-7-13 10:16 | 显示全部楼层
yzwzfyz 发表于 2021-7-12 17:24
仔细读手册:
1、数据是串行工作的,每位数据的切换是需要时间的,切换位数(CLK)不要超过允许的时间。
...

感谢您的回复,首先为了让转换结束再读数据,我在convst引脚置1后延时1us,是满足转换时间的650ns的,然后您说的数据读取时的切换位数不超过允许时间,手册里给了最小值,我在CLK每次转换后也延时1us,读取频率远没有到允许的最大值50MHz,最后您说的防止读到数据边缘该如何操作呢,我程序里就是参考0832的读取做的。
这是手册里的时序规格要求,红色划掉的是最小值。 Inked时序时间_LI.jpg


回复

使用道具 举报

ID:500971 发表于 2021-7-13 11:36 | 显示全部楼层
stc不是有自带ad吗
回复

使用道具 举报

ID:947166 发表于 2021-7-13 14:10 | 显示全部楼层
本帖最后由 Capta1nY 于 2021-7-13 14:20 编辑
5191 发表于 2021-7-13 11:36
stc不是有自带ad吗

是,但是目前电路已经设计好了,就想着能用就用吧,之前用过0832没啥问题,换了个结果调不出来了,您有什么建议吗
回复

使用道具 举报

ID:844772 发表于 2021-7-13 16:09 | 显示全部楼层
看你发的手册应该在CLK下沿读DO,但你程序写的是上沿读啊。
就这段  ad_clk = 1;
           dat <<= 1;Delay1us();
           if(ad_do) dat |= 0x0001;
           Delay1us();
           ad_clk = 0; Delay1us();
回复

使用道具 举报

ID:947166 发表于 2021-7-14 09:56 | 显示全部楼层
glinfei 发表于 2021-7-13 16:09
看你发的手册应该在CLK下沿读DO,但你程序写的是上沿读啊。
就这段  ad_clk = 1;
           dat

你说的有道理,我改成了
  1.   for(i=0; i<12; i++){
  2.                 ad_clk = 1;Delay1us();
  3.                 ad_clk = 0;
  4.                 dat <<= 1;
  5.                 if(ad_do) dat |= 0x0001;
  6.                 Delay1us();               
  7.   }
复制代码

结果还是没效果
回复

使用道具 举报

ID:947166 发表于 2021-7-15 10:46 | 显示全部楼层
问一下各位大佬,有没有可能是51的时钟频率不够,我查到的用这个AD的都是FPGA和32的
回复

使用道具 举报

ID:844772 发表于 2021-7-15 11:12 | 显示全部楼层
Capta1nY 发表于 2021-7-15 10:46
问一下各位大佬,有没有可能是51的时钟频率不够,我查到的用这个AD的都是FPGA和32的

我那天就想问,你手册上给的最大读取时间好短啊,比如T4 只有3ns,都不够if用的,能否先把ad_do赋值个中间变量,再去判断?另外那些我看延时也用不着了。
回复

使用道具 举报

ID:947166 发表于 2021-7-16 09:48 | 显示全部楼层
glinfei 发表于 2021-7-15 11:12
我那天就想问,你手册上给的最大读取时间好短啊,比如T4 只有3ns,都不够if用的,能否先把ad_do赋值个中 ...

放弃了,杠了几天没办法了,就用自带的AD吧,谢谢啦
回复

使用道具 举报

ID:708541 发表于 2021-7-16 15:49 | 显示全部楼层
单片机自带AD操作容易,有范例程序直接可以用,自带AD现在随便都10位和12位精度一般应用够用了,你自己用AD芯片程序和时序搞不对,就无法AD转换。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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