四足笔记

robot.c

 

#include "robot.h"
#include "delay.h"
/*
   __________ __________ _________________
  |1_____)0                  4(______5|
  |__|       |left FRONT right|        |__|
             |                |
             |                |
             |                |
   _________ |                | __________
  |7_____)6     ___________   2(______3|
  |__|                                 |__|
*/
void action(int num,int turn,int raise,u16 measure_time,bool move)
{
	if(MOVE==move)
	PCA_MG9XX(num+1,0,raise,1,1);//抬起
	PCA_MG9XX(num,0,turn,1,1);//哪个,开始角度[默认0],结束角度,模式,速度	
	if(MOVE==move)
	{
		if(num==0)			
			PCA_MG9XX(num+1,0,NOR_LU_2,1,1);//放下
		else if(num==6)
			PCA_MG9XX(num+1,0,NOR_LD_2,1,1);
		else if(num==2)
				PCA_MG9XX(num+1,0,NOR_RD_2,1,1);
		else
				PCA_MG9XX(num+1,0,NOR_RU_2,1,1);
	}
}

void home()
{
	action(0,NOR_LU_1,NOR_LU_2,10,STILL);
	action(2,NOR_RD_1,NOR_RD_2,10,STILL);
	action(4,NOR_RU_1,NOR_RU_2,10,STILL);
	action(6,NOR_LD_1,NOR_LD_2,10,STILL);
	//左上脚0-90向前,90-120高度下降--0
	//右下脚90-120向前,90-0高度下降--2//
	//右上脚90-120向前,90-0高度下降--4
	//左下脚0-90向前,90-120高度下降--6
}
void LowHome()//低姿态的原位置
{
	PCA_MG9XX(0,0,NOR_LU_1,2,1);
	PCA_MG9XX(2,0,NOR_RD_1,2,1);
	PCA_MG9XX(4,0,NOR_RU_1,2,1);
	PCA_MG9XX(6,0,NOR_LD_1,2,1);//锁定关节回归角度
	delay_ms(50);
	PCA_MG9XX(1,0,L_FUNUP,0,1);
	PCA_MG9XX(3,0,R_FUNUP,0,1);
	PCA_MG9XX(5,0,R_FUNUP,0,1);
	PCA_MG9XX(7,0,L_FUNUP,0,1);
	delay_ms(50);
}
void say_hello()//3,7可用
{
	int i;
	PCA_MG9XX(5,0,HELLO,0,0);
	for(i=0;i<8;i++)
	{
		PCA_MG9XX(4,0,90,1,5);
		delay_ms(20);
		PCA_MG9XX(4,0,120,1,5);
		delay_ms(20);
	}
	PCA_MG9XX(4,0,NOR_RU_1,0,0);
	PCA_MG9XX(5,0,NOR_RU_2,0,0);
}
//蜉蝣形式
void swim()
{
			action(0,WALK_F_L,L_UP,1,MOVE);
			action(4,WALK_F_R4,R_UP,1,MOVE);
			PCA_MG9XX(0,0,BACK_FL,1,10);//90
			PCA_MG9XX(4,0,BACK_FL,1,10);
			action(6,WALK_F_L4,UP_ADD,1,MOVE);
			action(2,WALK_F_R,UP_DE,1,MOVE);
			PCA_MG9XX(2,0,NOR_RD_1,1,10);//回归90度
			PCA_MG9XX(6,0,NOR_LD_1,1,10);//回归90度
}
void DogWalk()//3---7//1--5
{
	int i;
		//前后腿锁定180
	PCA_MG9XX(0,0,90,1,1);
	PCA_MG9XX(2,0,90,1,1);
	PCA_MG9XX(4,0,90,1,1);
	PCA_MG9XX(6,0,90,1,1);//锁定内关节回归角度
	
	PCA_MG9XX(1,0,90,1,1);
	PCA_MG9XX(3,0,85,1,1);//弥补机械上的误差
	PCA_MG9XX(5,0,90,1,1);
	PCA_MG9XX(7,0,100,1,1);//锁定外关节回归角度
	
	for(i=0;i<40;i++)
	{
		PCA_MG9XX(1,0,60,0,1);//1,5折叠
		PCA_MG9XX(5,0,60,0,1);
		delay_ms(50);
		PCA_MG9XX(1,0,90,0,1);
		PCA_MG9XX(5,0,90,0,1);
		delay_ms(50);
		PCA_MG9XX(3,0,55,0,1);//3,7
		PCA_MG9XX(7,0,70,0,1);
		delay_ms(50);
		PCA_MG9XX(3,0,85,0,1);
		PCA_MG9XX(7,0,100,0,1);
		delay_ms(50);
		
		//sportmini行走,有问题
//		PCA_MG9XX(1,0,60,0,1);//1,3折叠
//		PCA_MG9XX(3,0,55,0,1);
//		delay_ms(50);
//		PCA_MG9XX(1,0,90,0,1);
//		PCA_MG9XX(3,0,85,0,1);
//		delay_ms(50);
//		PCA_MG9XX(5,0,60,0,1);//5,7
//		PCA_MG9XX(7,0,70,0,1);
//		delay_ms(50);
//		PCA_MG9XX(5,0,90,0,1);
//		PCA_MG9XX(7,0,100,0,1);	
//		delay_ms(50);
	}
	home();
}
void jump()//跳跃
{
	//前后腿锁定180
	int i;
	PCA_MG9XX(0,0,90,1,1);
	PCA_MG9XX(2,0,90,1,1);
	PCA_MG9XX(4,0,90,1,1);
	PCA_MG9XX(6,0,90,1,1);//锁定内关节回归角度
	
	PCA_MG9XX(1,0,90,1,1);
	PCA_MG9XX(3,0,85,1,1);//弥补机械上的误差
	PCA_MG9XX(5,0,90,1,1);
	PCA_MG9XX(7,0,100,1,1);//锁定外关节回归角度
	for(i=0;i<50;i++)
	{
//		PCA_MG9XX(1,0,60,0,1);//1,7向内弯曲
//		PCA_MG9XX(7,0,60,0,1);
//		delay_ms(50);
//		PCA_MG9XX(1,0,90,0,1);
//		PCA_MG9XX(7,0,100,0,1);
//		delay_ms(50);
//		PCA_MG9XX(3,0,60,0,1);//3,5向外弯曲
//		PCA_MG9XX(5,0,60,0,1);
//		delay_ms(50);
//		PCA_MG9XX(3,0,85,0,1);
//		PCA_MG9XX(5,0,90,0,1);	
//		delay_ms(50);
		
		PCA_MG9XX(1,0,60,0,1);//1,7向内弯曲
		PCA_MG9XX(7,0,60,0,1);
		delay_ms(50);
		PCA_MG9XX(3,0,60,0,1);//3,5向外弯曲
		PCA_MG9XX(5,0,60,0,1);
		delay_ms(50);
		PCA_MG9XX(1,0,90,0,1);
		PCA_MG9XX(7,0,100,0,1);
		PCA_MG9XX(3,0,85,0,1);
		PCA_MG9XX(5,0,90,0,1);	
		delay_ms(50);
	}
	home();
}

void jog(int arg,bool dir)//小跑
{
	if(FORWARD==dir)
	{
		//两脚支撑
		PCA_MG9XX(1,0,L_UP,0,1);//抬脚
		PCA_MG9XX(3,0,UP_DE,0,1);
		delay_ms(30);
		PCA_MG9XX(0,0,60-arg,0,1);//转动 WALK_F_L
		PCA_MG9XX(2,0,60+arg,0,1);//WALK_F_R
		delay_ms(30);
		PCA_MG9XX(1,0,NOR_LU_2,0,1);//放脚
		PCA_MG9XX(3,0,NOR_RD_2,0,1);
		delay_ms(30);
		PCA_MG9XX(0,0,NOR_LU_1,0,1);//转动20--90 BACK_FL
		PCA_MG9XX(2,0,NOR_RD_1,0,1);//40//100--60
		delay_ms(30);
		
		PCA_MG9XX(5,0,R_UP,0,1);//抬脚
		PCA_MG9XX(7,0,UP_ADD,0,1);
		delay_ms(30);
		PCA_MG9XX(4,0,120+arg,0,1);//转动WALK_F_R4  160
		PCA_MG9XX(6,0,120-arg,0,1);//WALK_F_L4   80
		delay_ms(30);
		PCA_MG9XX(5,0,NOR_RU_2,0,1);//放脚
		PCA_MG9XX(7,0,NOR_LD_2,0,1);
		delay_ms(30);
		PCA_MG9XX(4,0,NOR_RU_1,0,1);//转动 BACK_FL
		PCA_MG9XX(6,0,NOR_LD_1,0,1);
		delay_ms(30);
	}else
	{
		//两脚支撑
		PCA_MG9XX(1,0,L_UP,0,1);//抬脚
		PCA_MG9XX(3,0,UP_DE,0,1);
		delay_ms(30);
		PCA_MG9XX(0,0,60+arg,0,1);//转动 WALK_F_L
		PCA_MG9XX(2,0,60-arg,0,1);//WALK_F_R
		delay_ms(30);
		PCA_MG9XX(1,0,NOR_LU_2,0,1);//放脚
		PCA_MG9XX(3,0,NOR_RD_2,0,1);
		delay_ms(30);
		PCA_MG9XX(0,0,NOR_LU_1,0,1);//转动20--90 BACK_FL
		PCA_MG9XX(2,0,NOR_RD_1,0,1);//40//100--60
		delay_ms(30);
		
		PCA_MG9XX(5,0,R_UP,0,1);//抬脚
		PCA_MG9XX(7,0,UP_ADD,0,1);
		delay_ms(30);
		PCA_MG9XX(4,0,120-arg,0,1);//转动WALK_F_R4  160
		PCA_MG9XX(6,0,120+arg,0,1);//WALK_F_L4   80
		delay_ms(30);
		PCA_MG9XX(5,0,NOR_RU_2,0,1);//放脚
		PCA_MG9XX(7,0,NOR_LD_2,0,1);
		delay_ms(30);
		PCA_MG9XX(4,0,NOR_RU_1,0,1);//转动 BACK_FL
		PCA_MG9XX(6,0,NOR_LD_1,0,1);
		delay_ms(30);
	}
}
void walk(int turn,int raise,bool dir)//0--2--4--6//蜘蛛单步缓慢走
{
	int i;
		//左上脚60度以下向前,90-120高度下降--0
		//右下脚60度以上向前,90-0高度下降--2//
		//右上脚120以上向前,90-0高度下降--4
		//左下脚120以下向前,90-120高度下降--6
	for(i=0;i<30;i++)
	{
		if(FORWARD==dir)
		{		
			action(0,WALK_F_L,L_UP,1,MOVE);//1腿迈出
			PCA_MG9XX(0,0,BACK_FL,1,1);//90//1腿回来
			action(2,WALK_F_R,UP_DE,1,MOVE);
			PCA_MG9XX(2,0,NOR_RD_1,1,1);//回归90度
			action(4,WALK_F_R4,R_UP,1,MOVE);
			PCA_MG9XX(4,0,BACK_FL,1,1);
			action(6,WALK_F_L4,UP_ADD,1,MOVE);
			PCA_MG9XX(6,0,NOR_LD_1,1,1);//回归90度
		}else
		{

		}
	}
}
void Turn(int arg,bool dir)//0--6--2--4
{
		if(LEFT==dir)
		{	
			//测试内调---完美
			PCA_MG9XX(1,0,L_UP,0,1);//抬脚
			PCA_MG9XX(3,0,UP_DE,0,1);
			delay_ms(30);
			PCA_MG9XX(0,0,60+arg,0,1);//转动 TURN_B_L1
			PCA_MG9XX(2,0,60+arg,0,1);//TURN_F_R2
			delay_ms(30);
			PCA_MG9XX(1,0,NOR_LU_2,0,1);//放脚
			PCA_MG9XX(3,0,NOR_RD_2,0,1);
			delay_ms(30);			
			PCA_MG9XX(5,0,R_UP,0,1);//抬脚
			PCA_MG9XX(7,0,UP_ADD,0,1);
			delay_ms(30);
			PCA_MG9XX(4,0,120+arg,0,1);//转动 TURN_F_R1
			PCA_MG9XX(6,0,120+arg,0,1);//TURN_B_L2
			delay_ms(30);
			PCA_MG9XX(5,0,NOR_RU_2,0,1);//放脚
			PCA_MG9XX(7,0,NOR_LD_2,0,1);
			delay_ms(30);
			PCA_MG9XX(0,0,NOR_LU_1,0,1);//转动
			PCA_MG9XX(2,0,NOR_RD_1,0,1);
			PCA_MG9XX(4,0,NOR_RU_1,0,1);//转动
			PCA_MG9XX(6,0,NOR_LD_1,0,1);
			delay_ms(60);
		}else//0--6--2--4
		{
			PCA_MG9XX(1,0,L_UP,0,1);//抬脚
			PCA_MG9XX(3,0,UP_DE,0,1);
			delay_ms(30);
			PCA_MG9XX(0,0,60-arg,0,1);//转动 TURN_F_L1
			PCA_MG9XX(2,0,60-arg,0,1);//TURN_B_R2
			delay_ms(30);
			PCA_MG9XX(1,0,NOR_LU_2,0,1);//放脚
			PCA_MG9XX(3,0,NOR_RD_2,0,1);
			delay_ms(30);			
			PCA_MG9XX(5,0,R_UP,0,1);//抬脚
			PCA_MG9XX(7,0,UP_ADD,0,1);
			delay_ms(30);
			PCA_MG9XX(4,0,60+arg,0,1);//转动TURN_B_R1
			PCA_MG9XX(6,0,60+arg,0,1);//TURN_F_L2
			delay_ms(30);
			PCA_MG9XX(5,0,NOR_RU_2,0,1);//放脚
			PCA_MG9XX(7,0,NOR_LD_2,0,1);
			delay_ms(30);
			PCA_MG9XX(0,0,NOR_LU_1,0,1);//转动
			PCA_MG9XX(2,0,NOR_RD_1,0,1);
			PCA_MG9XX(4,0,NOR_RU_1,0,1);//转动
			PCA_MG9XX(6,0,NOR_LD_1,0,1);
			delay_ms(60);

		}
}
void up_down()//0--6--2--4
{
	int i;
	PCA_MG9XX(0,0,NOR_LU_1,2,1);
	PCA_MG9XX(2,0,NOR_RD_1,2,1);
	PCA_MG9XX(4,0,NOR_RU_1,2,1);
	PCA_MG9XX(6,0,NOR_LD_1,2,1);//锁定关节回归角度
	for(i=0;i<15;i++)
	{
		//左上脚60度以下向前,90-120高度下降--0
		//右下脚60度以上向前,90-0高度下降--2//
		//右上脚120以上向前,90-0高度下降--4
		//左下脚120以下向前,90-120高度下降--6
		PCA_MG9XX(1,0,L_FUNUP,0,1);
		PCA_MG9XX(3,0,R_FUNUP,0,1);
		PCA_MG9XX(5,0,R_FUNUP,0,1);
		PCA_MG9XX(7,0,L_FUNUP,0,1);//锁定关节回归角度
		delay_ms(150);
		PCA_MG9XX(1,0,120,0,1);
		PCA_MG9XX(3,0,60,0,1);
		PCA_MG9XX(5,0,60,0,1);
		PCA_MG9XX(7,0,120,0,1);//锁定关节回归角度
		delay_ms(150);
	}
	home();
}
void Akid()
{
	int i;
	LowHome();
	//轮流上下
	for(i=0;i<15;i++)
	{
		PCA_MG9XX(1,0,L_FUNUP,1,10);
		delay_ms(50);
		PCA_MG9XX(1,0,130,1,10);
		delay_ms(50);
		PCA_MG9XX(3,0,R_FUNUP,1,10);
		delay_ms(50);
		PCA_MG9XX(3,0,50,1,10);
		delay_ms(50);
		PCA_MG9XX(5,0,R_FUNUP,1,10);
		delay_ms(50);
		PCA_MG9XX(5,0,50,1,10);
		delay_ms(50);
		
		PCA_MG9XX(7,0,L_FUNUP,1,10);//锁定关节回归角度
		delay_ms(50);
		PCA_MG9XX(7,0,130,1,10);//锁定关节回归角度
		delay_ms(50);

	}
}
//void Spider::wiring()
//{

//	
//}


robot.h

#ifndef __ROBOT_HPP
#define __ROBOT_HPP
#include "stm32_pca9685.h"
#include "delay.h"
#include "sys.h"
/*
   __________ __________ _________________
  |1_____)0                  4(______5|
  |__|       |left FRONT right|        |__|
             |                |
             |                |
             |                |
   _________ |                | __________
  |7_____)6     ___________   2(______3|
  |__|                                 |__|


*/
typedef  enum _BOOL
{
	false,
	true
}bool;
#define NOR_LU_1    60  //左上1关节常态   
#define NOR_LU_2    90//105///0

#define NOR_LD_1    120
#define NOR_LD_2    100//1086

#define NOR_RU_1    120
#define NOR_RU_2    90//72//4

#define NOR_RD_1    60
#define NOR_RD_2    85//78//2

#define BACK_FL     90
#define BACK_FR     90


//行走步距50
#define WALK_F_L   20//左向前60-15
#define WALK_F_R   100//右向前---2[原态60]
#define WALK_F_L4  80//左向前
#define WALK_F_R4  160///120+15
//转向
//左转
#define TURN_B_L1   90//左上脚向后    0
#define TURN_B_L2   150//左下脚向后   6
#define TURN_F_R2   90//右下脚向前    2
#define TURN_F_R1   150//右上脚向前    4

//右转
#define TURN_F_L1   30//左上脚向前   0
#define TURN_F_L2   90//左下脚向前   6
#define TURN_B_R1   90//右上脚向后   4
#define TURN_B_R2   30//右下脚向后   2

//抬脚放脚使用
#define L_UP          120//130//普通情况使用
#define L_DOWN				90//108//支撑
#define UP_ADD          130//直立加了10的特殊情况使用
#define DOWN_ADD				95
#define UP_DE          55//右下角使用
#define DOWN_DE				85


#define L_FUNUP       160
#define R_FUNUP       20
#define L_FUNDOWN     90
#define R_FUNDOWN     90


#define R_UP          60//50//抬起
#define R_DOWN				90//72//支撑

#define HELLO         40

#define FLY_BACK    90//关节回归角度      
#define FORWARD     true
#define BACK        false
	
#define MOVE     true
#define STILL    false
	
#define LEFT     true
#define RIGHT    false
void home(void);//原位置
void LowHome(void);
void action(int num,int turn,int raise,u16 measure_time,bool move);//某一条腿的封装
void walk(int turn,int raise,bool dir);//前进
void Turn(int arg,bool dir);//转向
void up_down(void);//原地上下
void say_hello(void);//打招呼
void swim(void);//浮游前进
void jump(void);//跳跃
void jog(int arg,bool dir);//小跑
void stroll(void);//踱步
void DogWalk(void);//小狗形态行走
void wiring(void);//腿轮流扭动
void Akid(void);//像小孩子一样调皮

#endif

pca9685.c

#include "stm32_pca9685.h"
#include "delay.h"
#include "math.h"



void pca_write(u8 adrr,u8 data)//向PCA写数据,adrrd地址,data数据
{ 
	IIC_Start();
	
	IIC_Send_Byte(pca_adrr);
	IIC_Wait_Ack();
	
	IIC_Send_Byte(adrr);
	IIC_Wait_Ack();
	
	IIC_Send_Byte(data);
	IIC_Wait_Ack();
	
	IIC_Stop();
}

u8 pca_read(u8 adrr)//从PCA读数据
{
	u8 data;
	IIC_Start();
	
	IIC_Send_Byte(pca_adrr);
	IIC_Wait_Ack();
	
	IIC_Send_Byte(adrr);
	IIC_Wait_Ack();
	
	IIC_Start();
	
	IIC_Send_Byte(pca_adrr|0x01);
	IIC_Wait_Ack();
	
	data=IIC_Read_Byte(0);
	IIC_Stop();
	
	return data;
}


void pca_setfreq(float freq)//设置PWM频率
{
		u8 prescale,oldmode,newmode;
		double prescaleval;
		freq *= 0.92; 
		prescaleval = 25000000;
		prescaleval /= 4096;
		prescaleval /= freq;
		prescaleval -= 1;
		prescale =floor(prescaleval + 0.5f);

		oldmode = pca_read(pca_mode1);
	
		newmode = (oldmode&0x7F) | 0x10; // sleep
	
		pca_write(pca_mode1, newmode); // go to sleep
	
		pca_write(pca_pre, prescale); // set the prescaler
	
		pca_write(pca_mode1, oldmode);
		delay_ms(2);
	
		pca_write(pca_mode1, oldmode | 0xa1); 
}

/*num:舵机PWM输出引脚0~15,on:PWM上升计数值0~4096,off:PWM下降计数值0~4096
一个PWM周期分成4096份,由0开始+1计数,计到on时跳变为高电平,继续计数到off时
跳变为低电平,直到计满4096重新开始。所以当on不等于0时可作延时,当on等于0时,
off/4096的值就是PWM的占空比。*/
void pca_setpwm(u8 num, u32 on, u32 off)
{
		pca_write(LED0_ON_L+4*num,on);
		pca_write(LED0_ON_H+4*num,on>>8);
		pca_write(LED0_OFF_L+4*num,off);
		pca_write(LED0_OFF_H+4*num,off>>8);
}


/*
	函数作用:初始化舵机驱动板
	参数:1.PWM频率
		  2.初始化舵机角度
*/
void PCA_MG9XX_Init(float hz,u8 angle)
{
	u32 off=0;
	IIC_Init();
	pca_write(pca_mode1,0x0);
	pca_setfreq(hz);//设置PWM频率
	off=(u32)(145+angle*2.4);
	pca_setpwm(0,0,off);pca_setpwm(1,0,off);pca_setpwm(2,0,off);pca_setpwm(3,0,off);
	pca_setpwm(4,0,off);pca_setpwm(5,0,off);pca_setpwm(6,0,off);pca_setpwm(7,0,off);
	pca_setpwm(8,0,off);pca_setpwm(9,0,off);pca_setpwm(10,0,off);pca_setpwm(11,0,off);
	pca_setpwm(12,0,off);pca_setpwm(13,0,off);pca_setpwm(14,0,off);pca_setpwm(15,0,off);
	delay_ms(500);
}

/*
	函数作用:控制舵机转动;
	参数:1.输出端口,可选0~15;
		  2.起始角度,可选0~180;
		  3.结束角度,可选0~180;
		  4.模式选择,0 表示函数内无延时,调用时需要在函数后另外加延时函数,且不可调速,第五个参数可填任意值;
					  1 表示函数内有延时,调用时不需要在函数后另外加延时函数,且不可调速,第五个参数可填任意值;
					  2 表示速度可调,第五个参数表示速度值;
		  5.速度,可填大于 0 的任意值,填 1 时速度最快,数值越大,速度越小;
	注意事项:模式 0和1 的速度比模式 2 的最大速度大;
*/
void PCA_MG9XX(u8 num,u8 start_angle,u8 end_angle,u8 mode,u8 speed)
{
	u8 i;
	u32 off=0;
	switch(mode)
	{
		case 0:
			off=(u32)(158+end_angle*2.2);
			pca_setpwm(num,0,off);
			break;
		case 1:
			off=(u32)(158+end_angle*2.2);
			pca_setpwm(num,0,off);
			if(end_angle>start_angle){delay_ms((u16)((end_angle-start_angle)*2.7));}
			else{delay_ms((u16)((start_angle-end_angle)*2.7));}
			break;
		case 2:
			if(end_angle>start_angle)
			{
				for(i=start_angle;i<=end_angle;i++)
				{
					off=(u32)(158+i*2.2);
					pca_setpwm(num,0,off);
					delay_ms(2);
					delay_us(speed*250);
				}
			}
			else if(start_angle>end_angle)
			{
				for(i=start_angle;i>=end_angle;i--)
				{
					off=(u32)(158+i*2.2);
					pca_setpwm(num,0,off);
					delay_ms(2);
					delay_us(speed*250);
				}
			}
			break;
	}
}


//----------------
//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9); 	//PB6,PB7 输出高
}
//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号                                                                                                                                            
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

pca9685.h

#ifndef __STM32PCA9685_H
#define __STM32PCA9685_H	

#include "stm32f10x.h"


#define pca_adrr 0x80

#define pca_mode1 0x0
#define pca_pre 0xFE

#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9

#define jdMIN  115 // minimum
#define jdMAX  590 // maximum
#define jd000  130 //0度对应4096的脉宽计数值
#define jd180  520 //180度对应4096的脉宽计算值



//IO方向设置
 
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

//IO操作函数	 
#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA	 
#define READ_SDA   PBin(7 )  //输入SDA 





void pca_write(u8 adrr,u8 data);
u8 pca_read(u8 adrr);
void PCA_MG9XX_Init(float hz,u8 angle);
void pca_setfreq(float freq);
void pca_setpwm(u8 num, u32 on, u32 off);
void PCA_MG9XX(u8 num,u8 start_angle,u8 end_angle,u8 mode,u8 speed);




//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号


#endif









 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值