標(biāo)題:
求求大神們看看代碼哪里出錯,編譯沒問題,舵機(jī)不動stm32+pca9685
[打印本頁]
作者:
eeeq
時間:
2021-2-27 15:55
標(biāo)題:
求求大神們看看代碼哪里出錯,編譯沒問題,舵機(jī)不動stm32+pca9685
#include "iic.h"
#include "gpio.h"
#include "delay.h"
#define TRUE 1
#define FALSE 0
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: void IIC_Start(void)
*功 能: 產(chǎn)生IIC起始信號
*******************************************************************************/
uint8_t IIC_Start(void)
{
SDA_H;
SCL_H;
delay_ms(5);
if(!SDA_read)
return FALSE;
SDA_L;
delay_ms(5);
if(SDA_read)
return FALSE;
SDA_L;
delay_ms(5);
return TRUE;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: void IIC_Stop(void)
*功 能: //產(chǎn)生IIC停止信號
*******************************************************************************/
void IIC_Stop(void)
{
SCL_L;
delay_ms(5);
SDA_L;
delay_ms(5);
SCL_H;
delay_ms(5);
SDA_H;
delay_ms(5);
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: uint8_t IIC_Wait_Ack(void)
*功 能: 等待應(yīng)答信號到來
//返回值:1,接收應(yīng)答失敗
// 0,接收應(yīng)答成功
*******************************************************************************/
uint8_t IIC_Wait_Ack(void)
{
SCL_L;
delay_ms(5);
SDA_H;
delay_ms(5);
SCL_H;
delay_ms(5);
if(SDA_read)
{
SCL_L;
delay_ms(5);
return FALSE;
}
SCL_L;
delay_ms(5);
return TRUE;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: void IIC_Ack(void)
*功 能: 產(chǎn)生ACK應(yīng)答
*******************************************************************************/
void IIC_Ack(void)
{
SCL_L;
delay_ms(5);
SDA_L;
delay_ms(5);
SCL_H;
delay_ms(5);
SCL_L;
delay_ms(5);
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: void IIC_NAck(void)
*功 能: 產(chǎn)生NACK應(yīng)答
*******************************************************************************/
void IIC_NAck(void)
{
SCL_L;
delay_ms(5);
SDA_H;
delay_ms(5);
SCL_H;
delay_ms(5);
SCL_L;
delay_ms(5);
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: void IIC_Send_Byte(uint8_t txd)
*功 能: IIC發(fā)送一個字節(jié)
*******************************************************************************/
void IIC_Send_Byte(uint8_t SendByte)
{
uint8_t i=8;
while(i--)
{
SCL_L;
delay_ms(5);
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
delay_ms(5);
SCL_H;
delay_ms(5);
}
SCL_L;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: uint8_t IIC_Read_Byte(unsigned char ack)
*功 能: //讀1串字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK
*******************************************************************************/
unsigned char IIC_Read_Byte(void)
{
uint8_t i=8;
uint8_t ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
delay_ms(5);
SCL_H;
delay_ms(5);
if(SDA_read)
{
ReceiveByte|=0x01;
}
}
SCL_L;
return ReceiveByte;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: unsigned char IIC_ReadOneByte(unsigned char I2C_Addr,unsigned char addr)
*功 能: 讀取指定設(shè)備 指定寄存器的一個值
輸入 I2C_Addr 目標(biāo)設(shè)備地址
addr 寄存器地址
返回 讀出來的值
*******************************************************************************/
uint8_t IIC_ReadOneByte(uint8_t SlaveAddress,uint16_t REG_Address,uint8_t* data)
{
if(!IIC_Start())
return FALSE;
IIC_Send_Byte(SlaveAddress);
if(!IIC_Wait_Ack())
{
IIC_Stop();
return FALSE;
}
IIC_Send_Byte((uint8_t) REG_Address>>8);
IIC_Wait_Ack();
IIC_Send_Byte((uint8_t) REG_Address & 0x00ff);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(SlaveAddress+1);
IIC_Wait_Ack();
*data= IIC_Read_Byte();
IIC_NAck();
IIC_Stop();
return TRUE;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data)
*功 能: 讀取指定設(shè)備 指定寄存器的 length個值
輸入 dev 目標(biāo)設(shè)備地址
reg 寄存器地址
length 要讀的字節(jié)數(shù)
*data 讀出的數(shù)據(jù)將要存放的指針
返回 讀出來的字節(jié)數(shù)量
*******************************************************************************/
uint8_t IICreadBytes(uint8_t SlaveAddress,uint16_t REG_Address,uint8_t len,uint8_t *data)
{
uint8_t i = 0;
if(!IIC_Start())
return FALSE;
IIC_Send_Byte(SlaveAddress);
if(!IIC_Wait_Ack())
{
IIC_Stop();
return FALSE;
}
IIC_Send_Byte((uint8_t) REG_Address>>8);
IIC_Wait_Ack();
IIC_Send_Byte(REG_Address&0x00ff);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(SlaveAddress+1);
IIC_Wait_Ack();
for(i = 0;i<len;i++)
{
if(i != (len -1))
{
data[i]= IIC_Read_Byte();
IIC_Ack();
}
else
{
data[i]= IIC_Read_Byte();
IIC_NAck();
}
}
IIC_Stop();
return len;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data)
*功 能: 將多個字節(jié)寫入指定設(shè)備 指定寄存器
輸入 dev 目標(biāo)設(shè)備地址
reg 寄存器地址
length 要寫的字節(jié)數(shù)
*data 將要寫的數(shù)據(jù)的首地址
返回 返回寫入長度
*******************************************************************************/
uint8_t IICwriteBytes(uint8_t dev, uint16_t reg, uint16_t length, uint8_t* data)
{
uint8_t count = 0;
IIC_Start();
IIC_Send_Byte(dev);
IIC_Wait_Ack();
IIC_Send_Byte(reg>>8);
IIC_Wait_Ack();
IIC_Send_Byte(reg & 0x00ff);
LEDx_GPIO_Config();
GPIO_SetBits(LED_GPIO_PORT,LED_PIN);
IIC_Wait_Ack();
for(count=0;count<length;count++)
{
IIC_Send_Byte(data[count]);
IIC_Wait_Ack();
}
IIC_Stop();
return length; //status == 0;
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: unsigned char IICwriteByte(unsigned char dev, unsigned char reg, unsigned char data)
*功 能: 寫入指定設(shè)備 指定寄存器一個字節(jié)
輸入 dev 目標(biāo)設(shè)備地址
reg 寄存器地址
data 將要寫入的字節(jié)
返回 1
*******************************************************************************/
uint8_t IICwriteByte(uint8_t dev, uint16_t reg, uint8_t data)
{
return IICwriteBytes(dev, reg, 1, &data);
}
/**************************實(shí)現(xiàn)函數(shù)********************************************
*函數(shù)原型: uint8_t IICwriteBit(uint8_t dev, uint8_t reg, uint8_t bitNum, uint8_t data)
*功 能: 讀 修改 寫 指定設(shè)備 指定寄存器一個字節(jié) 中的1個位
輸入 dev 目標(biāo)設(shè)備地址
reg 寄存器地址
bitNum 要修改目標(biāo)字節(jié)的bitNum位
data 為0 時,目標(biāo)位將被清0 否則將被置位
返回 成功 為1
失敗為0
*******************************************************************************/
uint8_t IICwriteBit(uint8_t dev, uint16_t reg, uint8_t bitNum, uint8_t data)
{
uint8_t b;
IIC_ReadOneByte(dev, reg, &b);
b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
return IICwriteByte(dev, reg, b);
}
復(fù)制代碼
#ifndef _IIC_H
#define _IIC_H
#include "stm32f4xx.h"
#include "pca9685.h"
#define I2C_SLAVE_ADDRESS7 0x80
#define SCL_H GPIO_WriteBit(GPIOF,GPIO_Pin_1,Bit_SET)
#define SCL_L GPIO_WriteBit(GPIOF,GPIO_Pin_1,Bit_RESET)
#define SDA_H GPIO_WriteBit(GPIOF,GPIO_Pin_0,Bit_SET)
#define SDA_L GPIO_WriteBit(GPIOF,GPIO_Pin_0,Bit_RESET)
#define SCL_read GPIO_ReadOutputDataBit(GPIOF,GPIO_Pin_1)
#define SDA_read GPIO_ReadOutputDataBit(GPIOF,GPIO_Pin_0)
void IIC_Init(void); //初始化IIC的IO口
uint8_t IIC_ReadOneByte(uint8_t SlaveAddress,uint16_t REG_Address,uint8_t* data);
unsigned char IICwriteByte(unsigned char dev, uint16_t reg, unsigned char data);
uint8_t IICwriteBytes(uint8_t dev, uint16_t reg, uint16_t length, uint8_t* data);
uint8_t IICwriteBit(uint8_t dev,uint16_t reg,uint8_t bitNum,uint8_t data);
uint8_t IICreadBytes(uint8_t SlaveAddress,uint16_t REG_Address,uint8_t len,uint8_t *data);
uint8_t IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(uint8_t txd);
uint8_t IIC_Read_Byte(void);
uint8_t IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);
#endif
復(fù)制代碼
#ifndef __PCA_H
#define __PCA_H
#include "stm32f4xx.h"
#define PCA9685_MODE1 0x0
#define PCA9685_SUBADR1 0x2
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4
#define pca_adrr 0x80
#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
#define PCA9685_PRESCALE 0xFE
void pca_write(uint8_t adrr,uint8_t data);
uint8_t pca_read(uint8_t adrr);
void pca_setfreq(float freq);
void setpwm(uint8_t num, uint32_t on, uint32_t off);
void pca_setpwm(uint8_t num,uint8_t off);
uint8_t transform(uint8_t angel);
#endif<div class="blockcode"><blockquote>
復(fù)制代碼
#include "iic.h"
#include "pca9685.h"
#include "math.h"
#include "delay.h"
void pca_setfreq(float freq)
{
float prescale = 25000000.0;
freq *= 1.024;
prescale = prescale/(4096*freq)-1;
IICwriteByte(pca_adrr,PCA9685_MODE1,0x10);
delay_ms(2);
IICwriteByte(pca_adrr,PCA9685_PRESCALE,(uint8_t) prescale);
delay_ms(2);
IICwriteByte(pca_adrr,PCA9685_MODE1,0x00);
delay_ms(2);
}
void setpwm(uint8_t num, uint32_t on, uint32_t off)
{
復(fù)制代碼
#include "delay.h"
void delay_us(uint32_t time){
uint16_t i=0;
while(time--){
i=10;//自己定義
while(i--) ;
}
}
//毫秒級的延時
void delay_ms(uint16_t time){
uint16_t i=0;
while(time--){
i=12000;//自己定義
while(i--) ;
}
}
復(fù)制代碼
#ifndef __LED_H
#define __LED_H
#include "stm32f4xx.h"
void delay_Init(u8 SYSCL);
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif
復(fù)制代碼
作者:
daemondong
時間:
2021-2-27 16:34
這個要有檢查的思路,首先確認(rèn)PCA9685硬件的地址是否是0x80
#define PCA9685_adrr 0x80// 1+A5+A4+A3+A2+A1+A0+w/r
//片選地址,將焊接點(diǎn)置1可改變地址,
// 當(dāng)IIC總 呱嫌 多片PCA9685或相同地址時才需焊接
然后確認(rèn)IIC是否工作正常,用讀命令讀PCA9685模式狀態(tài),看看能否讀出。
最后確定寫入?yún)?shù)是否正確。
作者:
ljjakey
時間:
2021-3-10 14:36
樓主解決了沒?
我的pca9685無法通訊
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1