四足筆記

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//108////////////6

#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









 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章