找回密码
 立即注册

QQ登录

只需一步,快速开始

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

用stc15w204s单片机的p1.3脚能模拟adc检测吗,定时器0我用在其它地方用了,

[复制链接]
跳转到指定楼层
楼主
各位大佬,用stc15w204s的p1.3脚能模拟adc检测吗,定时器0我用在其它地方用了,剩下的管脚我也一样用了,请求大家能给我一套可以直接调试的程序,官方的我没看懂,谢谢大家
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:89217 发表于 2020-8-6 15:44 | 只看该作者
检测电平咯,,
回复

使用道具 举报

板凳
ID:803579 发表于 2020-8-6 16:00 | 只看该作者

這款单片机是没有adc的,不晓得怎么检测,能给程序作参考吗
回复

使用道具 举报

地板
ID:803579 发表于 2020-8-6 16:02 | 只看该作者
啊h啊 发表于 2020-8-6 16:00
這款单片机是没有adc的,不晓得怎么检测,能给程序作参考吗

我所有的管脚都使用了,定时器0和2也在其它地方用了,只剩下一个p1.3的管脚
回复

使用道具 举报

5#
ID:401564 发表于 2020-8-6 17:28 | 只看该作者
这个单片机是没有ADC的
但凡是用STC的,基本就不是什么批量产品,肯定是有改动的空间的,直接换一个有ADC功能的单片机就可以了
不要用官方推荐的那种没有ADC功能单片机使用RC电路来实现ADC,那会乱的
直接换单片机最实用
回复

使用道具 举报

6#
ID:807591 发表于 2020-8-6 17:39 | 只看该作者
都不看说明书的?这个型号没有ADC,,要模拟adc基本上很难
回复

使用道具 举报

7#
ID:155507 发表于 2020-8-6 17:52 来自手机 | 只看该作者
巧妇难为无米之炊
回复

使用道具 举报

8#
ID:155507 发表于 2020-8-6 20:16 | 只看该作者
你可以参考这个



  1. /*---------------------------------------------------------------------*/
  2. /* --- STC MCU International Limited ----------------------------------*/
  3. /* --- STC 1T Series MCU Demo Programme -------------------------------*/
  4. /* --- Mobile: (86)13922805190 ----------------------------------------*/
  5. /* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
  6. /* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
  7. /* --- QQ:  800003751 -------------------------------------------------*/
  8. /* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
  9. /*---------------------------------------------------------------------*/



  10. /****************************
  11. 本示例在Keil开发环境下请选择Intel的8052芯片型号进行编译

  12. 本例程MCU的工作频率为22.1184MHz.

  13. 使用MCU自带的比较器进行ADC转换, 并通过串口输出结果. 用定时器0产生10us中断查询比较器的状态.

  14. 使用比较器做ADC, 原理图如下.
  15. 做ADC的原理是基于电荷平衡的计数式ADC.
  16. 电压从Vin输入, 通过100K+104滤波, 进入比较器的P5.5正输入端, 经过比较器的比较, 将结果输出到P1.5再通过100K+104滤波后送比较器P5.4负输入端,跟输入电压平衡.
  17. 设置两个变量: 计数周期(量程)adc_duty 和 比较结果高电平的计数值 adc, adc严格比例于输入电压.
  18. ADC的基准就是P1.5的高电平. 如果高电平准确,比较器的放大倍数足够大,则ADC结果会很准确.
  19. 当比较结果为高电平,则P1.5输出1, 并且adc+1.
  20. 当比较结果为低电平,则P1.5输出0.
  21. 每一次比较都判断计数周期是否完成,完成则adc里的值就是ADC结果.
  22. 电荷平衡计数式ADC的性能类似数字万用表用的双积分ADC, 当计数周期为20ms的倍数时,具有很强的抗工频干扰能力,很好的线性和精度.
  23. 原理可以参考ADD3501(3 1/2位数字万用表)或ADD3701(3 3/4位数字万用表), 也可以参考AD7740 VFC电路.

  24. 例: 比较一次的时间间隔为10us, 量程为10000, 则做1次ADC的时间为100ms. 比较器的响应时间越短, 则完成ADC就越快.

  25. 由于要求每次比较时间间隔都要相等,所以用C编程最好在定时器中断里进行, 定时器设置为自动重装, 高优先级中断, 其它中断均低优先级.
  26. 用汇编的话, 保证比较输出电平处理的时间要相等.


  27.                                          100K
  28.                             /| P5.5       ___
  29.                     P1.2   /+|---------o-|___|- ------- Vin
  30.                      .----<  | P5.4    |
  31.                      |     \-|---.     |
  32.                      |      \|   |     |
  33.                      |           |     |
  34.                      |    ___    |     |
  35.                      '---|___|---o     |
  36.                         100K     |     |
  37.                                 ---   ---
  38.                                 ---   ---
  39.                             104  |     |  104
  40.                                  |     |
  41.                                 ===   ===
  42.                                 GND   GND



  43. ******************************/

  44. #define MAIN_Fosc                22118400L        //定义主时钟
  45. #define        BaudRate1                9600ul                //定义波特率
  46. #define        ADC_SCALE                50000                //ADC满量程, 根据需要设置

  47. #include        "STC15Fxxxx.H"


  48. /*************        本地常量声明        **************/

  49. //CMPCR1
  50. #define        CMPEN        0x80        //1: 允许比较器, 0: 禁止,关闭比较器电源
  51. #define        CMPIF        0x40        //比较器中断标志, 包括上升沿或下降沿中断, 软件清0
  52. #define        PIE                0x20        //1: 比较结果由0变1, 产生上升沿中断
  53. #define        NIE                0x10        //1: 比较结果由1变0, 产生下降沿中断
  54. #define        PIS                0x08        //输入正极性选择, 0: 选择内部P5.5做正输入,           1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
  55. #define        NIS                0x04        //输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入.
  56. #define        CMPOE        0x02        //1: 允许比较结果输出到P1.2, 0: 禁止.
  57. #define        CMPRES        0x01        //比较结果, 1: CMP+电平高于CMP-,  0: CMP+电平低于CMP-,  只读

  58. //CMPCR2
  59. #define        INVCMPO        0x80        //1: 比较器输出取反,  0: 不取反
  60. #define        DISFLT        0x40        //1: 关闭0.1uF滤波,   0: 允许
  61. #define        LCDTY        0x00        //0~63, 比较结果变化延时周期数

  62. #define        TIM_16BitAutoReload                        0
  63. #define        TIM_16Bit                                        1
  64. #define        TIM_8BitAutoReload                        2
  65. #define        TIM_16BitAutoReloadNoMask        3

  66. #define        Pin0                0x01        //IO引脚 Px.0
  67. #define        Pin1                0x02        //IO引脚 Px.1
  68. #define        Pin2                0x04        //IO引脚 Px.2
  69. #define        Pin3                0x08        //IO引脚 Px.3
  70. #define        Pin4                0x10        //IO引脚 Px.4
  71. #define        Pin5                0x20        //IO引脚 Px.5
  72. #define        Pin6                0x40        //IO引脚 Px.6
  73. #define        Pin7                0x80        //IO引脚 Px.7
  74. #define        PinAll                0xFF        //IO所有引脚

  75. /*************        本地变量声明        **************/
  76. //sbit        P_ADC        = P1^2;        //P1.2 比较器转IO输出端
  77. sbit        P_ADC        = P1^4;        //P1.2 比较器转IO输出端
  78. u16                adc;                        //ADC中间值, 用户层不可见
  79. u16                adc_duty;                //ADC计数周期, 用户层不可见
  80. u16                adc_value;                //ADC值, 用户层使用
  81. bit                adc_ok;                        //ADC结束标志, 为1则adc_value的值可用. 此标志给用户层查询,并且清0


  82. /*************        本地函数声明        **************/
  83. void        TxString(u8 *puts);






  84. void main(void)
  85. {
  86.         u8        i;
  87.         u8        tmp[5];


  88. //IO口初始化
  89. //        P1n_push_pull(Pin2);                //P1.2设置为push-pull output
  90.         P1n_push_pull(Pin4);                //P1.2设置为push-pull output
  91.         P5n_pure_input(Pin4+Pin5);        //P5.4 P5.5设置为高阻输入


  92. //比较器初始化
  93.         CMPCR1 = 0;
  94.         CMPCR2 = 20;                //比较结果变化延时周期数, 0~63
  95.         CMPCR1 |= CMPEN;        //允许比较器                ENABLE,DISABLE
  96. //        CMPCR1 |= PIE;                //允许上升沿中断        ENABLE,DISABLE
  97. //        CMPCR1 |= NIE;                //允许下降沿中断        ENABLE,DISABLE
  98. //        CMPCR1 |= PIS;                //输入正极性选择, 0: 选择内部P5.5做正输入,           1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
  99.         CMPCR1 |= NIS;                //输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入
  100. //        CMPCR1 |= CMPOE;        //允许比较结果输出到P1.2,   ENABLE,DISABLE
  101. //        CMPCR2 |= INVCMPO;        //比较器输出取反,         ENABLE,DISABLE
  102.         CMPCR2 |= DISFLT;        //内部0.1uF滤波,          ENABLE,DISABLE


  103. //定时器0 初始化
  104.         TMOD &= ~0x0f;
  105.         Timer0_16bitAutoReload();        //设置为16位自动重装模式
  106.         Timer0_1T();        //设置为1T模式
  107.         ET0 = 1;                //允许中断
  108.         PT0 = 1;                //高优先级中断
  109.         TH0 = (u8)((65536 - MAIN_Fosc / 100000ul)>>8);                //重装值        100KHZ, 10us,        65536 - (MAIN_Fosc)/100000
  110.         TL0 = (u8)( 65536 - MAIN_Fosc / 100000ul);
  111.         TR0 = 1;                //开始运行


  112. //串口1初始化
  113.         S1_USE_P30P31();        //UART1 使用P30 P31口        默认
  114. //        S1_USE_P36P37();        //UART1 使用P36 P37口
  115. //        S1_USE_P16P17();        //UART1 使用P16 P17口

  116.         S1_8bit();                        //8位数据,波特率可变
  117.         S1_RX_Enable();                //允许接收
  118.         S1_TXD_RXD_OPEN();        //将TXD与RXD连接中继断开        默认
  119.         S1_BRT_UseTimer2();        //使用Timer2做波特率发生器
  120.         ES = 0;                                //禁止中断, 使用查询发送

  121.         Timer2_1T();        //Timer2 1T模式, 固定为16位自动重装
  122.     T2L = (65536 - (MAIN_Fosc/4/BaudRate1));   //设置波特率重装值
  123.     T2H = (65536 - (MAIN_Fosc/4/BaudRate1))>>8;
  124.         Timer2_Run();        //允许定时器2计数

  125.         EA = 1;                        //允许全局中断

  126.         TxString("\r\n使用比较器做ADC例子\r\n");        //SUART1发送一个字符串
  127.         

  128.         while (1)
  129.         {
  130.                 if(adc_ok)                //等待ADC结束
  131.                 {
  132.                         adc_ok = 0;                                //清除ADC已结束标志
  133.                         TxString("ADC = ");        //转十进制
  134.                         tmp[0] = adc_value / 10000 + '0';
  135.                         tmp[1] = adc_value % 10000 / 1000 + '0';
  136.                         tmp[2] = adc_value % 1000 / 100 + '0';
  137.                         tmp[3] = adc_value % 100 / 10 + '0';
  138.                         tmp[4] = adc_value % 10 + '0';
  139.                         for(i=0; i<4; i++)                //消无效0
  140.                         {
  141.                                 if(tmp[i] != '0')        break;
  142.                                 tmp[i] = ' ';
  143.                         }
  144.                         for(i=0; i<5; i++)                //发串口
  145.                         {
  146.                                 TI = 0;
  147.                                 SBUF = tmp[i];
  148.                                 while(!TI);
  149.                                 TI = 0;
  150.                         }
  151.                         TxString("\r\n");
  152.                 }
  153.         }
  154. }


  155. void TxString(u8 *puts)                //发送一个字符串
  156. {
  157.     for (; *puts != 0;        puts++)           //遇到停止符0结束
  158.         {
  159.                 TI = 0;
  160.                 SBUF = *puts;
  161.                 while(!TI);
  162.                 TI = 0;
  163.         }
  164. }


  165. /********************* Timer0中断函数************************/
  166. void timer0_int (void) interrupt TIMER0_VECTOR
  167. {
  168.         if((CMPCR1 & CMPRES) == 0)        P_ADC = 0;        //比较器输出高电平
  169.         else                                //P_ADC输出低电平, 给负输入端做反馈.
  170.         {
  171.                 P_ADC = 1;                        //P_ADC输出高电平, 给负输入端做反馈.
  172.                 adc ++;        //ADC计数+1
  173.         }

  174.         if(--adc_duty == 0)                        //ADC周期-1, 到0则ADC结束
  175.         {
  176.                 adc_duty = ADC_SCALE;        //周期计数赋初值
  177.                 adc_value = adc;                //保存ADC值
  178.                 adc = 0;                                //清除ADC值
  179.                 adc_ok = 1;                                //标志ADC已结束
  180.         }
  181. }





复制代码
回复

使用道具 举报

9#
ID:213173 发表于 2020-8-6 20:49 | 只看该作者
STC15W204S有8脚和16脚两种封装,楼主提到只能用P1.3,那只能是16脚封装,8脚封装的没有P1。楼主与其纠结怎么模拟adc不如直接更换内置ADC的STC15W404AS,两者管脚排列相同,价格相差几角钱。何况利用RC测量电压的精度取决于RC精度且受温度变化影响较大,不适合批量生产制作。
回复

使用道具 举报

10#
ID:213173 发表于 2020-8-6 21:30 | 只看该作者
模拟adc起码需要3个条件:1个普通IO口,一个外部中断口,一个定时器。楼主3个条件只具备1个半。
回复

使用道具 举报

11#
ID:803579 发表于 2020-8-7 10:07 | 只看该作者
angmall 发表于 2020-8-6 20:16
你可以参考这个

我想请问,如果与内部基准电压做比较是不是可以不用接p5.4
回复

使用道具 举报

12#
ID:147710 发表于 2020-8-7 10:18 | 只看该作者
这个型号有ADC


回复

使用道具 举报

13#
ID:146782 发表于 2020-8-7 11:58 | 只看该作者
模拟adc需要:1个普通IO口,一个外部中断口,一个定时器。直接换一个STC15W408AS吧
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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