有程友給我留言說需要一個紅外控制舵機的程序
但我沒有直接控制舵機的,只有控制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)
2019-5-29 22:19 上傳
點擊文件名下載附件
|