找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2334|回复: 1
收起左侧

通过单片机pcf8591电位器控制直流电机正反转 源程序Proteus仿真

[复制链接]
ID:816424 发表于 2020-11-23 09:22 | 显示全部楼层 |阅读模式
proteus和程序一起打包,送给有需要的小伙伴

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png
捕获.JPG

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

  3. typedef unsigned char uint8;
  4. typedef unsigned int uint16;
  5. typedef unsigned long uint32;
  6. sbit PWM01=P1^4;                                       
  7. sbit PWM02=P1^5;                                                  //电机1
  8. sbit PWM11=P1^6;                                       
  9. sbit PWM12=P1^7;                                                   //电机2
  10. sbit PWM21=P2^2;                                       
  11. sbit PWM22=P2^3;                                                        //电机3
  12. sbit PWM31=P3^6;                                       
  13. sbit PWM32=P3^7;                                                   //电机4
  14. sbit ADDRC = P1^0;
  15. sbit ADDRB = P1^1;
  16. sbit ADDRA = P1^2;//控制138译码器的三个引脚
  17. uint8 AD_value0 = 0;//AD值
  18. uint8 AD_value1 = 0;//AD值
  19. uint8 AD_value2 = 0;//AD值
  20. uint8 AD_value3 = 0;//AD值
  21. uint8 Top = 255;
  22. uint8 Low = 0;
  23. uint8 between0 = 127;
  24. uint8 between1 = 128;
  25. sbit I2C_SDA = P2^1;
  26. sbit I2C_SCL = P2^0;//I2C通信的两个引脚

  27. bit flag_300ms = 0;//300ms时间标志位
  28. uint8 T0RH = 0;//定时器高8位初值
  29. uint8 T0RL = 0;//定时器低8位初值
  30. //uint8 AD_value = 0;//AD值
  31. uint8 code led_char[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
  32.                                                  0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//LED段码

  33. void config_timer0(uint8 ms);
  34. uint8 get_ADC_vaule(uint8 chn);
  35. void motor_deal0();
  36. void motor_deal1();
  37. void motor_deal2();
  38. void motor_deal3();
  39. void main()
  40. {
  41.         config_timer0(1);//初始化通用定时器0,定时1ms
  42.         while(1)
  43.         {
  44.                 if(flag_300ms == 1)        //判断300ms时间是否到了
  45.                 {
  46.                         flag_300ms = 0;//清除标志位
  47.                         AD_value0 = get_ADC_vaule(0);//读取通道0的AD值
  48.                         AD_value1 = get_ADC_vaule(1);//读取通道0的AD值
  49.                         AD_value2 = get_ADC_vaule(2);//读取通道0的AD值
  50.                         AD_value3 = get_ADC_vaule(3);//读取通道0的AD值
  51.                           
  52.                 }               
  53.                 motor_deal0();       
  54.                 motor_deal1();
  55.                 motor_deal2();
  56.                 motor_deal3();
  57.         }
  58. }
  59. void motor_deal0()
  60. {
  61.         if(AD_value0 == between0 || AD_value0 == between1)                   //stop
  62.                 {  
  63.                                 PWM01=1;
  64.                                 PWM02=1;   
  65.                 }
  66.                 else if(AD_value0>=Low && AD_value0<between0)                   //正
  67.                 {
  68.                                 PWM01=0;
  69.                                 PWM02=1;
  70.                 }
  71.                 else                                         //反
  72.                 {
  73.                         PWM01=1;
  74.                          PWM02=0;
  75.                 }       
  76. }
  77. void motor_deal1()
  78. {
  79.         if(AD_value1 == between0 || AD_value1 == between1)                   //stop
  80.         {  
  81.                         PWM11=1;
  82.                         PWM12=1;
  83.         }
  84.         else if(AD_value1>=Low && AD_value1<between0)                   //正
  85.         {
  86.                         PWM11=0;
  87.                         PWM12=1;
  88.         }
  89.         else                                         //反
  90.         {
  91.                 PWM11=1;
  92.                  PWM12=0;
  93.         }       
  94. }
  95. void motor_deal2()
  96. {
  97.         if(AD_value2 == between0 || AD_value2 == between1)                   //stop
  98.         {  
  99.                         PWM21=1;
  100.                         PWM22=1;
  101.         }
  102.         else if(AD_value2>=Low && AD_value2<between0)                   //正
  103.         {
  104.                         PWM21=0;
  105.                         PWM22=1;
  106.         }
  107.         else                                         //反
  108.         {
  109.                 PWM21=1;
  110.                  PWM22=0;
  111.         }       
  112. }
  113. void motor_deal3()
  114. {
  115.         if(AD_value3 == between0 || AD_value3 == between1)                   //stop
  116.         {  
  117.                         PWM31=1;
  118.                         PWM32=1;
  119.         }
  120.         else if(AD_value3>=Low && AD_value3<between0)                   //正
  121.         {
  122.                         PWM31=0;
  123.                         PWM32=1;
  124.         }
  125.         else                                         //反
  126.         {
  127.                 PWM31=1;
  128.                  PWM32=0;
  129.         }       
  130. }
  131. void I2C_delay()//I2C延时函数
  132. {
  133.         _nop_();
  134.         _nop_();
  135.         _nop_();
  136.         _nop_();
  137. }

  138. void I2C_start()//I2C起始信号
  139. {
  140.         I2C_SDA = 1;
  141.         I2C_SCL = 1;
  142.         I2C_delay();
  143.         I2C_SDA = 0;
  144.         I2C_delay();
  145.         I2C_SCL = 0;
  146.         I2C_delay();
  147. }

  148. void I2C_stop()//I2C停止信号
  149. {
  150.         I2C_SDA = 0;
  151.         I2C_SCL = 0;
  152.         I2C_delay();
  153.         I2C_SCL = 1;
  154.         I2C_delay();
  155.         I2C_SDA = 1;
  156.         I2C_delay();
  157. }

  158. bit I2C_write(uint8 dat)//I2C写一个字节
  159. {
  160.         bit ack = 0;
  161.         uint8 mask = 0;
  162.         for(mask=0x80;mask!=0;mask>>=1)
  163.         {
  164.                 if((mask&dat) == 0)
  165.                         I2C_SDA = 0;
  166.                 else
  167.                         I2C_SDA = 1;
  168.                 I2C_delay();
  169.                 I2C_SCL = 1;
  170.                 I2C_delay();
  171.                 I2C_SCL = 0;
  172.                 I2C_delay();
  173.         }
  174.         I2C_SDA = 1;
  175.         I2C_delay();
  176.         I2C_SCL = 1;
  177.         I2C_delay();
  178.         ack = I2C_SDA;
  179.         I2C_delay();
  180.         I2C_SCL = 0;
  181.         I2C_delay();
  182.        
  183.         return (~ack);       
  184. }

  185. uint8 I2C_read_ACK()//I2C读一个字节,并发送应答位
  186. {
  187.         uint8 dat = 0;
  188.         uint8 mask = 0;
  189.         I2C_SDA = 1;
  190.         for(mask=0x80;mask!=0;mask>>=1)
  191.         {
  192.                 if(I2C_SDA == 0)
  193.                         dat = dat & (~mask);
  194.                 else
  195.                         dat = dat | mask;
  196.                 I2C_delay();
  197.                 I2C_SCL = 1;
  198.                 I2C_delay();
  199.                 I2C_SCL = 0;
  200.                 I2C_delay();
  201.         }
  202.         I2C_SDA = 0;
  203.         I2C_delay();
  204.         I2C_SCL = 1;
  205.         I2C_delay();
  206.         I2C_SCL = 0;
  207.         I2C_delay();

  208.         return dat;
  209. }

  210. uint8 I2C_read_NACK()//I2C读一个字节,并发送非应答位
  211. {
  212.         uint8 dat = 0;
  213.         uint8 mask = 0;
  214.         I2C_SDA = 1;
  215.         for(mask=0x80;mask!=0;mask>>=1)
  216.         {
  217.                 if(I2C_SDA == 0)
  218.                         dat = dat & (~mask);
  219.                 else
  220.                         dat = dat | mask;
  221.                 I2C_delay();
  222.                 I2C_SCL = 1;
  223.                 I2C_delay();
  224.                 I2C_SCL = 0;
  225.                 I2C_delay();
  226.         }
  227.         I2C_SDA = 1;
  228.         I2C_delay();
  229.         I2C_SCL = 1;
  230.         I2C_delay();
  231.         I2C_SCL = 0;
  232.         I2C_delay();

  233.         return dat;
  234. }

  235. uint8 get_ADC_vaule(uint8 chn)//获取AD值
  236. {
  237.         uint8 value = 0;
  238.         I2C_start();//I2C起始信号
  239.         if(!I2C_write(0X90))//写入PCF8591地址及读写选择位为写
  240.         {
  241.                 I2C_stop();
  242.                 return 0;
  243.         }
  244. //        I2C_write(0X40 | chn);//写入PCF8591通道0
  245.         I2C_write(0x00 | chn);//写入PCF8591通道0
  246.         I2C_start();//I2C起始信号
  247.         I2C_write(0x48<<1 | 0x01);
  248.         I2C_read_ACK();//提供转换所需的时钟信号
  249.         value = I2C_read_NACK();//读取上一次转换的结果
  250.         I2C_stop();//I2C结束信号

  251.         return value;
  252. }

  253. void config_timer0(uint8 ms)//配置定时器0的通用函数
  254. {
  255.         uint32 temp =0 ;
  256.         temp = 11059200/12;
  257.         temp = (temp * ms)/1000;
  258.         temp = 65536 - (temp + 12);
  259.         T0RH = (uint8)(temp >> 8);
  260.         T0RL = (uint8)temp;

  261.         TMOD = TMOD & 0XF0;
  262.         TMOD = TMOD | 0X01;
  263.         TH0 = T0RH;
  264.         TL0 = T0RL;
  265.         EA = 1;
  266.         ET0 = 1;
  267.         TR0 = 1;
  268. }
  269. ……………………

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

所有资料51hei提供下载:
电位器控制电机正反转四通道ok.zip (130.46 KB, 下载次数: 35)

评分

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

查看全部评分

回复

使用道具 举报

ID:143767 发表于 2020-11-26 13:18 | 显示全部楼层
用proteus仿真了一下,当电位器调节到50%的时候电机不能立即停止,要等个十几秒钟,请问楼主这是什么原因,希望给解答一下,谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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