概述
项目需要使用多路舵机,为了体型得选择stm32c8t6,同时需要用八个舵机sg90,很麻烦,于是找到了pac9685的拓展驱动板,买回来之后发现了问题,商家给的都是51的代码,网上搜到的都是32其他型号的,或者是c8t6 HAL库的,在网上不是用不了就是要钱,最终找到一个古老的博客。
GitHub - github150620/stm32-pca9685-sg90

这个是接线图,其中建议v+连5v,不然舵机可能动不了,下面给出代码
代码
main.c
#include "sg90.h"
void delay(int i) {
while (i) {
i--;
}
}
int main(void) {
SG90_Init();
while(1){
SG90_SetAngle(0, 0);
delay(80000000);
SG90_SetAngle(0, 90);
delay(80000000);
SG90_SetAngle(0, 180);
delay(80000000);
}
}
里面SG90_SetAngle(id,angle)
id就是连接的号0~15,看原理图,angle是要旋转的角度
pac9685.c
#include "stm32f10x.h"
#define PCA9685_I2C_ADDR 0x40
#define MODE1 0x00
#define MODE2 0x01
#define SUBADR1 0x02
#define SUBADR2 0x03
#define SUBADR3 0x04
#define ALLCALLADR 0x05
#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09
#define LED1_ON_L 0x0A
#define LED1_ON_H 0x0B
#define LED1_OFF_L 0x0C
#define LED1_OFF_H 0x0D
#define LED2_ON_L 0x0E
#define LED2_ON_H 0x0F
#define LED2_OFF_L 0x10
#define LED2_OFF_H 0x11
#define LED3_ON_L 0x12
#define LED3_ON_H 0x13
#define LED3_OFF_L 0x14
#define LED3_OFF_H 0x15
#define LED4_ON_L 0x16
#define LED4_ON_H 0x17
#define LED4_OFF_L 0x18
#define LED4_OFF_H 0x19
#define LED5_ON_L 0x1A
#define LED5_ON_H 0x1B
#define LED5_OFF_L 0x1C
#define LED5_OFF_H 0x1D
#define LED6_ON_L 0x1E
#define LED6_ON_H 0x1F
#define LED6_OFF_L 0x20
#define LED6_OFF_H 0x21
#define LED7_ON_L 0x22
#define LED7_ON_H 0x23
#define LED7_OFF_L 0x24
#define LED7_OFF_H 0x25
#define LED8_ON_L 0x26
#define LED8_ON_H 0x27
#define LED8_OFF_L 0x28
#define LED8_OFF_H 0x29
#define LED9_ON_L 0x2A
#define LED9_ON_H 0x2B
#define LED9_OFF_L 0x2C
#define LED9_OFF_H 0x2D
#define LED10_ON_L 0x2E
#define LED10_ON_H 0x2F
#define LED10_OFF_L 0x30
#define LED10_OFF_H 0x31
#define LED11_ON_L 0x32
#define LED11_ON_H 0x33
#define LED11_OFF_L 0x34
#define LED11_OFF_H 0x35
#define LED12_ON_L 0x36
#define LED12_ON_H 0x37
#define LED12_OFF_L 0x38
#define LED12_OFF_H 0x39
#define LED13_ON_L 0x3A
#define LED13_ON_H 0x3B
#define LED13_OFF_L 0x3C
#define LED13_OFF_H 0x3D
#define LED14_ON_L 0x3E
#define LED14_ON_H 0x3F
#define LED14_OFF_L 0x40
#define LED14_OFF_H 0x41
#define LED15_ON_L 0x42
#define LED15_ON_H 0x43
#define LED15_OFF_L 0x44
#define LED15_OFF_H 0x45
#define PRE_SCALE 0xFE
#define MODE1_RESTART 0x80
#define MODE1_EXTCLK 0x40
#define MODE1_AI 0x20
#define MODE1_SLEEP 0x10
#define MODE1_ALLCALL 0x01
static void delay(int i) {
while (i) {
i--;
}
}
void I2C2_Init() {
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_initStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
I2C_initStructure.I2C_ClockSpeed = 400000; // 400KHz
I2C_initStructure.I2C_Mode = I2C_Mode_I2C;
I2C_initStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_initStructure.I2C_OwnAddress1 = 0x77;
I2C_initStructure.I2C_Ack = I2C_Ack_Enable;
I2C_initStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C2, &I2C_initStructure);
I2C_Cmd(I2C2, ENABLE);
}
void PCA9685_WriteReg(u8 addr, u8 value) {
I2C_AcknowledgeConfig(I2C2, ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C2, (PCA9685_I2C_ADDR<<1)&0xfe, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C2, addr);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C2, value);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C2, ENABLE);
}
void PCA9685_ReadReg(u8 addr, u8 *value) {
I2C_AcknowledgeConfig(I2C2, ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C2, (PCA9685_I2C_ADDR<<1)&0xfe, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C2, addr);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C2, ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C2, (PCA9685_I2C_ADDR<<1)|0x01, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_AcknowledgeConfig(I2C2, DISABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
*value = I2C_ReceiveData(I2C2);
I2C_GenerateSTOP(I2C2, ENABLE);
}
void PCA9685_SetChannelDuty(u8 channel, u32 on, u32 off) {
I2C_AcknowledgeConfig(I2C2, ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C2, (PCA9685_I2C_ADDR<<1)&0xfe, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C2, LED0_ON_L+4*channel);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C2, on&0xff);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C2, (on>>8)&0xff);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C2, off&0xff);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C2, (off>>8)&0xff);
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C2, ENABLE);
}
void PCA9685_Init() {
u8 value;
I2C2_Init();
// The PRE_SCALE register can only be set when the SLEEP bit of MODE1 register is set to logic 1.
PCA9685_WriteReg(MODE1, MODE1_SLEEP);
PCA9685_WriteReg(PRE_SCALE, 121); // (25000000/4096/50)-1
PCA9685_WriteReg(MODE1, 0);
PCA9685_WriteReg(MODE1, MODE1_RESTART|MODE1_AI|MODE1_ALLCALL);
while (1) {
PCA9685_ReadReg(MODE1, &value);
if ((value&MODE1_RESTART)==0) { // Restart OK.
break;
}
delay(100000);
}
}
pca9685.h
#ifndef _PCA9685_H
#define _PCA9685_H
#include "stm32f10x.h"
void PCA9685_Init();
// channel: 0 ~ 15
// on: 0 ~ 4095
// off: 0 ~ 4095
void PCA9685_SetChannelDuty(u8 channel, u32 on, u32 off);
#endif
sg90.c
#include "pca9685.h"
void SG90_Init() {
PCA9685_Init();
}
void SG90_SetAngle(u8 id, u8 angle) {
PCA9685_SetChannelDuty(id, 0, (u32)(4095*((angle/180.0)*2.0+0.5)/20.0));
}
sg90.h
#ifndef _SG90_H
#define _SG90_H
#include "pca9685.h"
void SG90_Init();
void SG90_SetAngle(u8 id, u8 angle);
#endif
完整测试项目见百度网盘信息
项目链接
链接:https://pan.baidu.com/s/1pV6lL0C0lDvbcEoQoQF-qw?pwd=1234
提取码:1234
--来自百度网盘超级会员V3的分享
参考文章


&spm=1001.2101.3001.5002&articleId=137474707&d=1&t=3&u=864abba506af4f8c9ddbf6db968d2ba0)
9130

被折叠的 条评论
为什么被折叠?



