proteus和程序一起打包,送给有需要的小伙伴
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- typedef unsigned long uint32;
- sbit PWM01=P1^4;
- sbit PWM02=P1^5; //电机1
- sbit PWM11=P1^6;
- sbit PWM12=P1^7; //电机2
- sbit PWM21=P2^2;
- sbit PWM22=P2^3; //电机3
- sbit PWM31=P3^6;
- sbit PWM32=P3^7; //电机4
- sbit ADDRC = P1^0;
- sbit ADDRB = P1^1;
- sbit ADDRA = P1^2;//控制138译码器的三个引脚
- uint8 AD_value0 = 0;//AD值
- uint8 AD_value1 = 0;//AD值
- uint8 AD_value2 = 0;//AD值
- uint8 AD_value3 = 0;//AD值
- uint8 Top = 255;
- uint8 Low = 0;
- uint8 between0 = 127;
- uint8 between1 = 128;
- sbit I2C_SDA = P2^1;
- sbit I2C_SCL = P2^0;//I2C通信的两个引脚
- bit flag_300ms = 0;//300ms时间标志位
- uint8 T0RH = 0;//定时器高8位初值
- uint8 T0RL = 0;//定时器低8位初值
- //uint8 AD_value = 0;//AD值
- uint8 code led_char[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//LED段码
- void config_timer0(uint8 ms);
- uint8 get_ADC_vaule(uint8 chn);
- void motor_deal0();
- void motor_deal1();
- void motor_deal2();
- void motor_deal3();
- void main()
- {
- config_timer0(1);//初始化通用定时器0,定时1ms
- while(1)
- {
- if(flag_300ms == 1) //判断300ms时间是否到了
- {
- flag_300ms = 0;//清除标志位
- AD_value0 = get_ADC_vaule(0);//读取通道0的AD值
- AD_value1 = get_ADC_vaule(1);//读取通道0的AD值
- AD_value2 = get_ADC_vaule(2);//读取通道0的AD值
- AD_value3 = get_ADC_vaule(3);//读取通道0的AD值
-
- }
- motor_deal0();
- motor_deal1();
- motor_deal2();
- motor_deal3();
- }
- }
- void motor_deal0()
- {
- if(AD_value0 == between0 || AD_value0 == between1) //stop
- {
- PWM01=1;
- PWM02=1;
- }
- else if(AD_value0>=Low && AD_value0<between0) //正
- {
- PWM01=0;
- PWM02=1;
- }
- else //反
- {
- PWM01=1;
- PWM02=0;
- }
- }
- void motor_deal1()
- {
- if(AD_value1 == between0 || AD_value1 == between1) //stop
- {
- PWM11=1;
- PWM12=1;
- }
- else if(AD_value1>=Low && AD_value1<between0) //正
- {
- PWM11=0;
- PWM12=1;
- }
- else //反
- {
- PWM11=1;
- PWM12=0;
- }
- }
- void motor_deal2()
- {
- if(AD_value2 == between0 || AD_value2 == between1) //stop
- {
- PWM21=1;
- PWM22=1;
- }
- else if(AD_value2>=Low && AD_value2<between0) //正
- {
- PWM21=0;
- PWM22=1;
- }
- else //反
- {
- PWM21=1;
- PWM22=0;
- }
- }
- void motor_deal3()
- {
- if(AD_value3 == between0 || AD_value3 == between1) //stop
- {
- PWM31=1;
- PWM32=1;
- }
- else if(AD_value3>=Low && AD_value3<between0) //正
- {
- PWM31=0;
- PWM32=1;
- }
- else //反
- {
- PWM31=1;
- PWM32=0;
- }
- }
- void I2C_delay()//I2C延时函数
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- void I2C_start()//I2C起始信号
- {
- I2C_SDA = 1;
- I2C_SCL = 1;
- I2C_delay();
- I2C_SDA = 0;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- void I2C_stop()//I2C停止信号
- {
- I2C_SDA = 0;
- I2C_SCL = 0;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SDA = 1;
- I2C_delay();
- }
- bit I2C_write(uint8 dat)//I2C写一个字节
- {
- bit ack = 0;
- uint8 mask = 0;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if((mask&dat) == 0)
- I2C_SDA = 0;
- else
- I2C_SDA = 1;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- I2C_SDA = 1;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- ack = I2C_SDA;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
-
- return (~ack);
- }
- uint8 I2C_read_ACK()//I2C读一个字节,并发送应答位
- {
- uint8 dat = 0;
- uint8 mask = 0;
- I2C_SDA = 1;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if(I2C_SDA == 0)
- dat = dat & (~mask);
- else
- dat = dat | mask;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- I2C_SDA = 0;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- return dat;
- }
- uint8 I2C_read_NACK()//I2C读一个字节,并发送非应答位
- {
- uint8 dat = 0;
- uint8 mask = 0;
- I2C_SDA = 1;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if(I2C_SDA == 0)
- dat = dat & (~mask);
- else
- dat = dat | mask;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- I2C_SDA = 1;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- return dat;
- }
- uint8 get_ADC_vaule(uint8 chn)//获取AD值
- {
- uint8 value = 0;
- I2C_start();//I2C起始信号
- if(!I2C_write(0X90))//写入PCF8591地址及读写选择位为写
- {
- I2C_stop();
- return 0;
- }
- // I2C_write(0X40 | chn);//写入PCF8591通道0
- I2C_write(0x00 | chn);//写入PCF8591通道0
- I2C_start();//I2C起始信号
- I2C_write(0x48<<1 | 0x01);
- I2C_read_ACK();//提供转换所需的时钟信号
- value = I2C_read_NACK();//读取上一次转换的结果
- I2C_stop();//I2C结束信号
- return value;
- }
- void config_timer0(uint8 ms)//配置定时器0的通用函数
- {
- uint32 temp =0 ;
- temp = 11059200/12;
- temp = (temp * ms)/1000;
- temp = 65536 - (temp + 12);
- T0RH = (uint8)(temp >> 8);
- T0RL = (uint8)temp;
- TMOD = TMOD & 0XF0;
- TMOD = TMOD | 0X01;
- TH0 = T0RH;
- TL0 = T0RL;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
电位器控制电机正反转四通道ok.zip
(130.46 KB, 下载次数: 35)
|