有程友给我留言说需要一个红外控制舵机的程序
但我没有直接控制舵机的,只有控制16路舵机的程序,现在发上来提供参考
舵机可以通过串口控制,也可以用红外控制(具体使用请看程序内备注)
单片机源程序如下:
- #include "PCA9685_TJ.h"
- #include <stdio.h>
- #include <math.h>
- /*使用说明:
- 在main主程序
- PCA9685_init();
- 在main主程序的while加入
- PCA9685_main(); //注: 必需放在UART1_main();的前面
- */
- #define PCA9685_adrr 0x80// 1+A5+A4+A3+A2+A1+A0+w/r
- #define PCA9685_SUBADR1 0x2
- #define PCA9685_SUBADR2 0x3
- #define PCA9685_SUBADR3 0x4
- #define PCA9685_MODE1 0x0
- #define PCA9685_PRESCALE 0xFE
- #define LED0_ON_L 0x6
- #define LED0_ON_H 0x7
- #define LED0_OFF_L 0x8
- #define LED0_OFF_H 0x9
- #define ALLLED_ON_L 0xFA
- #define ALLLED_ON_H 0xFB
- #define ALLLED_OFF_L 0xFC
- #define ALLLED_OFF_H 0xFD
-
- uchar mm,nn;
- uint SERV0; //存储值
- /*---------------------------------------------------------------
- IIC初始化
- ----------------------------------------------------------------*/
- void init()
- {
- sda=1; //sda scl使用前被拉高
- delay100us(1);
- scl=1;
- delay100us(1);
- }
- /*---------------------------------------------------------------
- IIC启动
- ----------------------------------------------------------------*/
- void start()
- {
- sda=1;
- delay100us(1);
- scl=1; //scl高 sda拉低 IIC启动
- delay100us(1);
- sda=0;
- delay100us(1);
- scl=0;
- delay100us(1);
- }
- /*---------------------------------------------------------------
- IIC停止
- ----------------------------------------------------------------*/
- void stop()
- {
- sda=0;
- delay100us(1);
- scl=1;
- delay100us(1);
- sda=1;
- delay100us(1);
- }
- /*---------------------------------------------------------------
- IIC应答
- ----------------------------------------------------------------*/
- void ACK()
- {
- uchar i;
- scl=1;
- delay100us(1);
- while((sda=1)&&(i<255)) {
- i++;
- }
- scl=0;
- delay100us(1);
- }
- /*---------------------------------------------------------------
- 写字节
- ----------------------------------------------------------------*/
- void write_byte(uchar byte)
- {
- uchar i,temp;
- temp=byte;
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- scl=0;
- delay100us(1);
- sda=CY;
- delay100us(1);
- scl=1;
- delay100us(1);
- }
- scl=0;
- delay100us(1);
- sda=1;
- delay100us(1);
- }
- /*---------------------------------------------------------------
- 读字节
- ----------------------------------------------------------------*/
- uchar read_byte()
- {
- uchar i,j,k;
- scl=0;
- delay100us(1);
- sda=1;
- delay100us(1);
- for(i=0;i<8;i++)
- {
- delay100us(1);
- scl=1;
- delay100us(1);
- if(sda==1)
- {
- j=1;
- }
- else j=0;
- k=(k<< 1)|j;
- scl=0;
- }
- delay100us(1);
- return k;
- }
- /*---------------------------------------------------------------
- PCA9685
- ----------------------------------------------------------------*/
- /*---------------------------------------------------------------
- 写数据到PCA9685
- ----------------------------------------------------------------*/
- void PCA9685_write(uchar address,uchar date)
- {
- start();
- write_byte(PCA9685_adrr);
- ACK();
- write_byte(address);
- ACK();
- write_byte(date);
- ACK();
- stop();
- }
- /*---------------------------------------------------------------
- 从PCA9685读数据有返回值
- ----------------------------------------------------------------*/
- uchar PCA9685_read(uchar address)
- {
- uchar date;
- start();
- write_byte(PCA9685_adrr);
- ACK();
- write_byte(address);
- ACK();
- start();
- write_byte(PCA9685_adrr|0x01);
- ACK();
- date=read_byte();
- stop();
- return date;
- }
- /*---------------------------------------------------------------
- PCA9685复位
- ----------------------------------------------------------------*/
- void reset(void)
- {
- PCA9685_write(PCA9685_MODE1,0x0);
- }
- void begin(void)
- {
- reset();
- }
- /*---------------------------------------------------------------
- PCA9685修改频率
- ----------------------------------------------------------------*/
- void setPWMFreq(float freq)
- {
- uint prescale,oldmode,newmode;
- float prescaleval;
- freq *= 0.92; // Correct for overshoot in the frequency setting
- prescaleval = 25000000;
- prescaleval /= 4096;
- prescaleval /= freq;
- prescaleval -= 1;
- prescale = floor(prescaleval + 0.5);
-
- oldmode = PCA9685_read(PCA9685_MODE1);
- newmode = (oldmode&0x7F) | 0x10; // sleep
- PCA9685_write(PCA9685_MODE1, newmode); // go to sleep
- PCA9685_write(PCA9685_PRESCALE, prescale); // set the prescaler
- PCA9685_write(PCA9685_MODE1, oldmode);
- delay1ms(10);
- PCA9685_write(PCA9685_MODE1, oldmode | 0xa1);
- }
- void setPWM(uint num, uint on, uint off)
- {
- PCA9685_write(LED0_ON_L+4*num,on);
- PCA9685_write(LED0_ON_H+4*num,on>>8);
- PCA9685_write(LED0_OFF_L+4*num,off);
- PCA9685_write(LED0_OFF_H+4*num,off>>8);
- }
- void PCA9685_init() {
- init(); //初始化
- begin(); //初始化
- setPWMFreq(50); //设置50hz
- for(nn=0;nn<16;nn++) { //初始化
- setPWM(nn, 0, SERVOMAX);
- }
- }
- void PCA9685_main() {
- if(buf1[0]!=0x00 && cmd1==1){
- switch(buf1[0])
- {
- case 0x31: //串口输入1~
- mm=0;break;
- case 0x32: //串口输入2~
- mm=1;break;
- case 0x33: //串口输入3~
- mm=2;break;
- case 0x34: //串口输入4~
- mm=3;break;
- case 0x35: //串口输入5~
- mm=4;break;
- case 0x36: //串口输入6~
- mm=5;break;
- case 0x37: //串口输入7~
- mm=6;break;
- case 0x38: //串口输入8~
- mm=7;break;
- case 0x39: //串口输入9~
- mm=8;break;
- case 0x41: //串口输入A~
- mm=9;break;
- case 0x42: //串口输入B~
- mm=10;break;
- case 0x43: //串口输入C~
- mm=11;break;
- case 0x44: //串口输入D~
- mm=12;break;
- case 0x45: //串口输入E~
- mm=13;break;
- case 0x46: //串口输入F~
- mm=14;break;
- case 0x47: //串口输入G~
- mm=15;break;
- default:break; //接受到其它数据,蜂鸣器响
- }
- if(SERV0==SERVO110){ SERV0=SERVOMAX; } else { SERV0=SERVO110; }
- setPWM(mm, 0, SERV0);
- mm=999;
- }
- }
复制代码 全部资料51hei下载地址:
STC89C52RC+串口+红外控制16路舵机.zip
(70.37 KB, 下载次数: 67)
|