找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC12C2052AD单片机芯片中关于AD转换的相关内容

[复制链接]
跳转到指定楼层
楼主
ID:695961 发表于 2020-3-1 16:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用芯片自带的AD转换器,按芯片说明书中提供的典型线路图连接方案。发现使用查询方式AD转换没有问题,获取的输出转换电压和实际输入电压,大约相差正负0.2V左右。但是使用中断方式,仅在芯片上电触发一次,然后就不动了。代码也检查了N多遍,真心看不出还有什么问题。请问各位大神遇到过这种问题吗?该芯片测得的直流电压会相差这么多吗?谁用过这款芯片?

单片机代码如下:
  1. #include <intrins.h>
  2. #include <STC12C2052AD.H>
  3. #include "UART.H"

  4. volatile uint8 COMMAND;

  5. #define ADC_POWER     0x80                // 1000 0000
  6. #define ADC_FLAG      0x10                // 0001        0000
  7. #define ADC_START     0x08                // 0000 1000

  8. #define ADC_SPEEDLL   0x00                // 0000 0000
  9. #define ADC_SPEEDL          0x20                // 0010 0000
  10. #define ADC_SPEEDH    0x40                // 0100 0000
  11. #define ADC_SPEEDHH   0x60                // 0110 0000

  12. // 延时函数
  13. void Delay(uint16 n)
  14. {
  15.         uint16 x;
  16.         while(n--)
  17.         {
  18.                 x = 5000;
  19.                 while(x--);
  20.         }
  21. }

  22. // AD中断(这里出现问题,上电触发一次,然后就不再触发)
  23. void AdcISR() interrupt 5
  24. {
  25.         ADC_CONTR &= ~ADC_FLAG;
  26.         PutChar(ADC_DATA);
  27.         
  28.         // 开始下一次转换
  29.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 6 | ADC_START;
  30.         Delay(10);
  31. }

  32. // 初始化AD
  33. void InitAdc()
  34. {
  35.         P1 = P1M0 = P1M1 = 0xFF;                                // 将所有P1口全部设置为开漏(Open Drain)
  36.         ADC_DATA = 0;
  37.         
  38.         // 清空DA转换的结果
  39.         //ADC_CONTR = ADC_POWER | ADC_SPEEDHH;        
  40.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 6 | ADC_START;
  41.         Delay(10);
  42. }

  43. // 查询方式获取AD的值
  44. uint8 GetAdcResult()
  45. {
  46.         ADC_CONTR = ADC_POWER | ADC_SPEEDHH | 6 | ADC_START;
  47.         _nop_();
  48.         _nop_();
  49.         _nop_();
  50.         _nop_();
  51.         while(!(ADC_CONTR & ADC_FLAG));
  52.         
  53.         // 清空位
  54.         ADC_CONTR &= ~ADC_FLAG;
  55.         
  56.         // 返回转换结果
  57.         return ADC_DATA;
  58. }

  59. // 软件延时500ms
  60. void Delay500ms()                //@11.0592MHz
  61. {
  62.         unsigned char i, j, k;

  63.         i = 22;
  64.         j = 3;
  65.         k = 227;
  66.         do
  67.         {
  68.                 do
  69.                 {
  70.                         while (--k);
  71.                 } while (--j);
  72.         } while (--i);
  73. }


  74. void main()
  75. {
  76.         InitUART();                // 初始化串口
  77.         InitAdc();                // 初始化ADC
  78.         
  79.         
  80.         // 中断方式使用AD,使用查询方式时,注释下面两行
  81.         AUXR |= 0x10;
  82.         IE = 0xB0;                // 芯片说明书上给出的是0xA0,会将串口通讯的中断屏蔽,这里我改为了0xB0
  83.         
  84.         while(1)
  85.         {
  86.                 ;
  87.                
  88.                 // 查询方式使用AD,中断方式注释下面两行
  89. //                Delay500ms();
  90. //                PutChar(GetAdcResult());
  91.         }
  92. }
复制代码



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

使用道具 举报

沙发
ID:213173 发表于 2020-3-1 17:56 | 只看该作者
没有看到开总中断和开ADC中断
回复

使用道具 举报

板凳
ID:695961 发表于 2020-3-1 18:03 | 只看该作者
刚刚发完帖后,又仔细的检查了一下代码。发现这个问题可能是中断造成的。因为我在中断响应程序中调用了将数据发送到串口的操作,这种操作会触发串口发送数据完成的中断。

我将中断程序改为如下:

  1. void AdcISR() interrupt 5
  2. {
  3.         ADC_CONTR &= ~ADC_FLAG;
  4.        
  5.         PutChar(0xFF);
  6.         PutChar(0xFE);
  7.         PutChar(ADC_DATA);
  8.        
  9.         // 开始下一次转换
  10.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 6 | ADC_START;
  11. }
复制代码


在串口调试工具中发现接收窗仅打印了一个FF,然后就不动了。

查询手册发现,虽然没有设置串口优先级寄存器的情况下,同级的串口中断的优先级比AD优先执行,但是串口中断并不会打断AD中断的执行。所以程序就停止在了putchar中,因为putchar会等待串口中断执行完成将TI设置为0才往下执行。

所以,在主函数中将串口中断的优先级提高一级就可以正常工作了。

  1. void main()
  2. {
  3.         // 中断方式使用AD,使用查询方式时,注释下面两行
  4.         PS = 1;
  5.         AUXR |= 0x10;
  6.         IE = 0xB0;                // 芯片说明书上给出的是0xA0,会将串口通讯的中断屏蔽,这里我改为了0xB0
  7.         //PADC_SPI = 1;        // 高优先级
  8.        
  9.         InitUART();                // 初始化串口
  10.         InitAdc();                // 初始化ADC
  11.        
  12.         while(1)
  13.         {
  14.                 ;
  15.                
  16.                 // 查询方式使用AD,中断方式注释下面两行
  17. //                Delay500ms();
  18. //                PutChar(GetAdcResult());
  19.         }
  20. }
复制代码
回复

使用道具 举报

地板
ID:695961 发表于 2020-3-1 18:06 | 只看该作者
wulin 发表于 2020-3-1 17:56
没有看到开总中断和开ADC中断

谢谢您,我的问题已经解决了。开AD中断是

AUXR |= 0x10;
IE = 0xB0;

开总中断在是InitUART中做了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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