第一步:AS5600获取角度
首先需要注意的是:这个代码不是我写的,是B站慕静诚贵大佬开源分享的,我就是想学习一下, 然后自绘一个驱动板、再搭配动量伦玩玩,所以今天我开始了大佬的群主学习!有说的不对的地方,请随时指出,我是菜鸡,很多地方都不懂~
代码分析
首先我们要明白,如果单纯的只是用AS5600去读取电机的位置角度相关信息,我们需要什么?不需要电机转,我们用手扭动~那你再想想需要什么去获取角度?
答案:MCU与AS5600进行通讯,读取相关寄存器的值。
然后我们就明白了,只是单纯用到了一个通讯接口,而AS5600通讯接口有很多,我这里展示常用的IIC通讯。
为了与SimpleFOC原来的文件夹相对应,这里依然参照simpleFOC中的Arduino的目录格式!
? Arduino源代码排版格式
? KEIL源代码排版格式
这里我不得不再感慨一下大佬的计数,移植的好标准!!!很多文件看起来特别舒服!
OK,接下来就开始代码的分析了,首先我们知道我们就是单纯用到了IIC与AS5600进行通讯,所以配置一个IIC通讯接口就好,其次为了显示数据信息,配置一下USART,通过串口调试助手把东西打印出来!
我这里使用的STM32F103VET6野火指南者开发板,所以我就配置了一下通讯,如下图所示
然后生成代码就好。
然后把相关.c文件添加进相关目录文件夹下,如图二所述。
值得注意的是:图2中.c文件前面没有+号的代表这个我全部注释掉了整个文件,所以没用到!后期驱动电机的适合才会用到。
foc_common文件
这个文件夹里面就是一些默认参数值设置、正弦余弦等函数、pid算法、micro函数等,都不需要更改!
值得注意的是:如果不是STM32F1的主控,关于micro函数需要更换频率!否则时间不对。
foc_base_classes
这个文件夹中的Sensor.c文件主要是AS5600传感器相关功能,比如获取角度、获取方向、获取速度等等。
#include "Sensor.h"
#include <stdlib.h>
#include <string.h>
#include "time_utils.h"
#include "foc_utils.h"
static void update(void *pobj)
{
sensor * _this=(sensor *)pobj;
float val = _this->getSensorAngle(_this);
_this->angle_prev_ts = micros();
float d_angle = val - _this->angle_prev;
if(ABS(d_angle) > (0.8f * _2PI) ) _this->full_rotations += ( d_angle > 0 ) ? -1 : 1;
_this->angle_prev = val;
}
static float getVelocity(void *pobj)
{
sensor * _this=(sensor *)pobj;
float Ts = (_this->angle_prev_ts - _this->vel_angle_prev_ts) * 1e-6;
if(Ts <= 0) Ts = 1e-3f;
float vel = ( (float)(_this->full_rotations - _this->vel_full_rotations) * _2PI + (_this->angle_prev - _this->vel_angle_prev) ) / Ts;
_this->vel_angle_prev = _this->angle_prev;
_this->vel_full_rotations = _this->full_rotations;
_this->vel_angle_prev_ts = _this->angle_prev_ts;
return vel;
}
static void init(void *pobj)
{
sensor * _this=(sensor *)pobj;
_this->getSensorAngle(_this);
delay(1);
_this->vel_angle_prev = _this->getSensorAngle(_this);
_this->vel_angle_prev_ts = micros();
delay(1);
_this->getSensorAngle(_this);
delay(1);
_this->angle_prev = _this->getSensorAngle(_this);
_this->angle_prev_ts = micros();
}
static float getMechanicalAngle(void *pobj)
{
sensor * _this=(sensor *)pobj;
return _this->angle_prev;
}
static float getAngle(void *pobj)
{
sensor * _this=(sensor *)pobj;
return (float)_this->full_rotations * _2PI + _this->angle_prev;
}
static double getPreciseAngle(void *pobj)
{
sensor * _this=(sensor *)pobj;
return (double)_this->full_rotations * (double)_2PI + (double)_this->angle_prev;
}
static signed int getFullRotations(void *pobj)
{
sensor * _this=(sensor *)pobj;
return _this->full_rotations;
}
static int needsSearch(void *pobj)
{
return 0;
}
void new_sensor(sensor* pObj)
{
memset(pObj, 0, sizeof(sensor));
pObj->init = init;
pObj->update = update;
pObj->getMechanicalAngle = getMechanicalAngle;
pObj->getAngle = getAngle;
pObj->getPreciseAngle = getPreciseAngle;
pObj->getVelocity = getVelocity;
pObj->getFullRotations = getFullRotations;
pObj->needsSearch = needsSearch;
pObj->getSensorAngle = NULL;
}
我们用的时候只需要使用new_sensor函数,因为其他的函数都被这个函数调用了的!
foc_driver
这个文件夹,在获取角度的时候什么都没用到,后期驱动电机的时候会用到。
foc_sensor
这个文件夹中,主要是讲磁传感器和IIC进行联系起来!!!IIC读取函数什么的都在iic.c文件,等会看。
#include "MagneticSensorI2C.h"
#include <string.h>
#include <stdlib.h>
#include "stdio.h"
#include "time_utils.h"
#include "foc_utils.h"
/** Typical configuration for the 12bit AMS AS5600 magnetic sensor over I2C interface */
MagneticSensorI2CConfig AS5600_I2C = {
.chip_address = 0x36,
.bit_resolution = 12,
.angle_register = 0x0C,
.data_start_bit = 11
};
static void init(void *pObj, void *_wire){
MagneticSensor_i2c *_this=(MagneticSensor_i2c *)pObj;
_this->wire = (iic *)_wire;
// I2C communication begin
_this->wire->init(_this->wire); //初始化IIC硬件对象
delay(5);
_this->SenSor.init(_this); //初始化传感器对象
}
static int read(MagneticSensor_i2c * _this) {
// read the angle register first MSB then LSB
unsigned char readArray[2];
unsigned short readValue = 0;
//调用iic读取as5600寄存器内的角度数据值
_this->wire->read_accord_to_input_length(_this->wire, _this->chip_address, _this->angle_register_msb, 2, readArray);
// depending on the sensor architecture there are different combinations of
// LSB and MSB register used bits
// AS5600 uses 0..7 LSB and 8..11 MSB
// AS5048 uses 0..5 LSB and 6..13 MSB
readValue = ( readArray[1] & _this->lsb_mask );
readValue += ( ( readArray[0] & _this->msb_mask ) << _this->lsb_used );
return readValue;
}
// function reading the raw counter of the magnetic sensor
static int getRawCount(MagneticSensor_i2c * _this){
return (int) read(_this);
}
// Shaft angle calculation
// angle is in radians [rad]
static float getSensorAngle(void * _this){
MagneticSensor_i2c * pObj;
pObj=(MagneticSensor_i2c *)_this;
// (number of full rotations)*2PI + current sensor angle
return ( getRawCount(pObj) / (float)pObj->cpr) * _2PI ;
}
//MagneticSensorI2c构造函数
void new_MagneticSensor_i2c(MagneticSensor_i2c * pObj,MagneticSensorI2CConfig config)
{
//clear
memset(pObj, 0, sizeof(MagneticSensor_i2c));
new_sensor(&pObj->SenSor);
pObj->chip_address = config.chip_address;
pObj->angle_register_msb = config.angle_register;
pObj->cpr = 1 << config.bit_resolution ;
int bits_used_msb = config.data_start_bit - 7;
pObj->lsb_used=config.bit_resolution-bits_used_msb;
pObj->lsb_mask=(unsigned char)((1 << pObj->lsb_used) - 1);
pObj->msb_mask=(unsigned char)((1 << bits_used_msb) - 1);
pObj->SenSor.getSensorAngle=getSensorAngle;
pObj->wire=NULL;
pObj->init=init;
}
foc_hardware
这个文件夹的iic.c文件就是iic通讯,比如读取、开始iic、停止iic等等。
#include "iic.h"
#include <stm32f1xx.h>
#include <string.h>
#include <stdlib.h>
#include "stdio.h"
#define fac_us 72
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define GPIOA_ODR_Addr (GPIOA_BASE+12)
#define GPIOB_ODR_Addr (GPIOB_BASE+12)
#define GPIOC_ODR_Addr (GPIOC_BASE+12)
#define GPIOD_ODR_Addr (GPIOD_BASE+12)
#define GPIOE_ODR_Addr (GPIOE_BASE+12)
#define GPIOF_ODR_Addr (GPIOF_BASE+12)
#define GPIOG_ODR_Addr (GPIOG_BASE+12)
#define GPIOA_IDR_Addr (GPIOA_BASE+8)
#define GPIOB_IDR_Addr (GPIOB_BASE+8)
#define GPIOC_IDR_Addr (GPIOC_BASE+8)
#define GPIOD_IDR_Addr (GPIOD_BASE+8)
#define GPIOE_IDR_Addr (GPIOE_BASE+8)
#define GPIOF_IDR_Addr (GPIOF_BASE+8)
#define GPIOG_IDR_Addr (GPIOG_BASE+8)
#define high 1
#define low 0
typedef enum out_status
{
Input,
Output ,
}pin_status;
void set_pin(unsigned int addr, unsigned char bitnum, unsigned char _status) {
MEM_ADDR(BITBAND(addr, bitnum))= _status;
}
unsigned char read_pin(unsigned int addr, unsigned char bitnum) {
return MEM_ADDR(BITBAND(addr, bitnum));
}
static void set_pin_outmode(void * _pObj, pin_status _status)
{
iic * _this=(iic *)_pObj;
switch(_this->sda_port)
{
case 'A':
{
if(_this->sda_pin < 8){
unsigned char move_bit = _this->sda_pin << 2;
GPIOA->CRL&=~(unsigned int)(15<<move_bit);
if(_status==Input){
GPIOA->CRL|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOA->CRL|=(unsigned int)3<<move_bit;
}
}
else
{
unsigned char move_bit = (_this->sda_pin - 8 ) << 2;
GPIOA->CRH&=~(unsigned int)( 15 << move_bit);
if(_status==Input){
GPIOA->CRH|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOA->CRH|=(unsigned int)3<<move_bit;
}
}
break;
}
case 'B':
{
if(_this->sda_pin < 8){
unsigned char move_bit = _this->sda_pin << 2;
GPIOB->CRL&=~(unsigned int)(15<<move_bit);
if(_status==Input){
GPIOB->CRL|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOB->CRL|=(unsigned int)3<<move_bit;
}
}
else
{
unsigned char move_bit = (_this->sda_pin - 8 ) << 2;
GPIOB->CRH&=~(unsigned int)( 15 << move_bit);
if(_status==Input){
GPIOB->CRH|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOB->CRH|=(unsigned int)3<<move_bit;
}
}
break;
}
case 'C':
{
if(_this->sda_pin < 8){
unsigned char move_bit = _this->sda_pin << 2;
GPIOC->CRL&=~(unsigned int)(15<<move_bit);
if(_status==Input){
GPIOC->CRL|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOC->CRL|=(unsigned int)3<<move_bit;
}
}
else
{
unsigned char move_bit = (_this->sda_pin - 8 ) << 2;
GPIOC->CRH&=~(unsigned int)( 15 << move_bit);
if(_status==Input){
GPIOC->CRH|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOC->CRH|=(unsigned int)3<<move_bit;
}
}
break;
}
case 'D':
{
if(_this->sda_pin < 8){
unsigned char move_bit = _this->sda_pin << 2;
GPIOD->CRL&=~(unsigned int)(15<<move_bit);
if(_status==Input){
GPIOD->CRL|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOD->CRL|=(unsigned int)3<<move_bit;
}
}
else
{
unsigned char move_bit = (_this->sda_pin - 8 ) << 2;
GPIOD->CRH&=~(unsigned int)( 15 << move_bit);
if(_status==Input){
GPIOD->CRH|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOD->CRH|=(unsigned int)3<<move_bit;
}
}
break;
}
case 'E':
{
if(_this->sda_pin < 8){
unsigned char move_bit = _this->sda_pin << 2;
GPIOE->CRL&=~(unsigned int)(15<<move_bit);
if(_status==Input){
GPIOE->CRL|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOE->CRL|=(unsigned int)3<<move_bit;
}
}
else
{
unsigned char move_bit = (_this->sda_pin - 8 ) << 2;
GPIOE->CRH&=~(unsigned int)( 15 << move_bit);
if(_status==Input){
GPIOE->CRH|=(unsigned int)8<<move_bit;
}
else if(_status==Output){
GPIOE->CRH|=(unsigned int)3<<move_bit;
}
}
break;
}
default:
break;
}
}
static GPIO_TypeDef * get_port(char _para)
{
GPIO_TypeDef * pObj=NULL;
switch(_para)
{
case 'A': pObj=GPIOA;
break;
case 'B': pObj=GPIOB;
break;
case 'C': pObj=GPIOC;
break;
case 'D': pObj=GPIOD;
break;
case 'E': pObj=GPIOE;
break;
default:
break;
}
return pObj;
}
static void clk_enable(char _para)
{
switch(_para)
{
case 'A': __HAL_RCC_GPIOA_CLK_ENABLE();
break;
case 'B': __HAL_RCC_GPIOB_CLK_ENABLE();
break;
case 'C': __HAL_RCC_GPIOC_CLK_ENABLE();
break;
case 'D': __HAL_RCC_GPIOD_CLK_ENABLE();
break;
case 'E': __HAL_RCC_GPIOE_CLK_ENABLE();
break;
default:
break;
}
}
static void get_addr_value(void * pObj)
{
iic * _this=(iic *)pObj;
switch(_this->scl_port)
{
case 'A': _this->scl_out_addr=GPIOA_ODR_Addr;
break;
case 'B': _this->scl_out_addr=GPIOB_ODR_Addr;
break;
case 'C': _this->scl_out_addr=GPIOC_ODR_Addr;
break;
case 'D': _this->scl_out_addr=GPIOD_ODR_Addr;
break;
case 'E': _this->scl_out_addr=GPIOE_ODR_Addr;
break;
default:
break;
}
switch(_this->sda_port)
{
case 'A': _this->sda_out_addr=GPIOA_ODR_Addr;
_this->sda_in_addr=GPIOA_IDR_Addr;
break;
case 'B': _this->sda_out_addr=GPIOB_ODR_Addr;
_this->sda_in_addr=GPIOB_IDR_Addr;
break;
case 'C': _this->sda_out_addr=GPIOC_ODR_Addr;
_this->sda_in_addr=GPIOC_IDR_Addr;
break;
case 'D': _this->sda_out_addr=GPIOD_ODR_Addr;
_this->sda_in_addr=GPIOD_IDR_Addr;
break;
case 'E': _this->sda_out_addr=GPIOE_ODR_Addr;
_this->sda_in_addr=GPIOE_IDR_Addr;
break;
default:
break;
}
}
static void udelay(unsigned int nus)
{
unsigned int ticks;
unsigned int told,tnow,tcnt=0;
unsigned int reload=SysTick->LOAD;
ticks=nus*fac_us;
told=SysTick->VAL;
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;
}
};
}
static void init(void * pObj)
{
iic * _this=(iic *)pObj;
GPIO_InitTypeDef GPIO_Initure;
clk_enable(_this->scl_port);
clk_enable(_this->sda_port);
HAL_GPIO_WritePin(get_port(_this->scl_port), 1 << _this->scl_pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(get_port(_this->sda_port), 1 << _this->sda_pin, GPIO_PIN_RESET);
GPIO_Initure.Pin = 1 << _this->scl_pin ;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_Initure.Pull = GPIO_NOPULL;
GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(get_port(_this->scl_port), &GPIO_Initure);
GPIO_Initure.Pin = 1 << _this->sda_pin ;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_Initure.Pull = GPIO_NOPULL;
GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(get_port(_this->sda_port), &GPIO_Initure);
get_addr_value(_this);
set_pin(_this->sda_out_addr, _this->sda_pin, high);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
}
static void start(void * pObj)
{
iic * _this=(iic *)pObj;
set_pin_outmode(_this, Output);
set_pin(_this->sda_out_addr, _this->sda_pin, high);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
udelay(4);
set_pin(_this->sda_out_addr, _this->sda_pin, low);
udelay(4);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
}
static void stop(void * pObj)
{
iic * _this=(iic *)pObj;
set_pin_outmode(_this, Output);
set_pin(_this->scl_out_addr, _this->scl_pin, low);
set_pin(_this->sda_out_addr, _this->sda_pin, low);
udelay(4);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
set_pin(_this->sda_out_addr, _this->sda_pin, high);
udelay(4);
}
static unsigned char wait_ack(void * pObj)
{
unsigned char ucErrTime=0;
iic * _this=(iic *)pObj;
set_pin_outmode(_this, Input);
set_pin(_this->sda_out_addr, _this->sda_pin, high);
udelay(1);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
udelay(1);
while(read_pin(_this->sda_in_addr, _this->sda_pin) )
{
ucErrTime++;
if(ucErrTime>250)
{
_this->stop(_this);
return 1;
}
}
set_pin(_this->scl_out_addr, _this->scl_pin, low);
return 0;
}
static void ack(void * pObj)
{
iic * _this=(iic *)pObj;
set_pin(_this->scl_out_addr, _this->scl_pin, low);
set_pin_outmode(_this, Output);
set_pin(_this->sda_out_addr, _this->sda_pin, low);
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, low);
}
static void nack(void * pObj)
{
iic * _this=(iic *)pObj;
set_pin(_this->scl_out_addr, _this->scl_pin, low);
set_pin_outmode(_this, Output);
set_pin(_this->sda_out_addr, _this->sda_pin, high);
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, low);
}
static void send_byte(void * pObj, unsigned char txd)
{
unsigned char t;
iic * _this=(iic *)pObj;
set_pin_outmode(_this, Output);
set_pin(_this->scl_out_addr, _this->scl_pin, low);
for(t=0;t<8;t++)
{
set_pin(_this->sda_out_addr, _this->sda_pin, (txd&0x80)>>7);;
txd<<=1;
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, low);
udelay(2);
}
}
static unsigned char read_byte(void * pObj, unsigned char ACK)
{
unsigned char i,receive=0;
iic * _this=(iic *)pObj;
set_pin_outmode(_this, Input);
for(i=0;i<8;i++ )
{
set_pin(_this->scl_out_addr, _this->scl_pin, low);
udelay(2);
set_pin(_this->scl_out_addr, _this->scl_pin, high);
receive<<=1;
if(read_pin(_this->sda_in_addr, _this->sda_pin))receive++;
udelay(1);
}
if (!ACK){
nack(_this);
}
else{
ack(_this);
}
return receive;
}
static unsigned char write_accord_to_input_length(void * pObj, unsigned char addr, unsigned char reg, unsigned char len, unsigned char *buf)
{
unsigned char i;
iic * _this=(iic *)pObj;
_this->start(_this);
_this->send_byte(_this, (addr << 1) | 0);
if(_this->wait_ack(_this))
{
_this->stop(_this);
return 1;
}
_this->send_byte(_this, reg);
_this->wait_ack(_this);
for(i=0;i<len;i++)
{
_this->send_byte(_this, buf[i]);
if(_this->wait_ack(_this))
{
_this->stop(_this);
return 1;
}
}
_this->stop(_this);
return 0;
}
static unsigned char read_accord_to_input_length(void * pObj, unsigned char addr, unsigned char reg, unsigned char len, unsigned char *buf)
{
iic * _this=(iic *)pObj;
_this->start(_this);
_this->send_byte(_this, (addr << 1) | 0);
if(_this->wait_ack(_this))
{
_this->stop(_this);
return 1;
}
_this->send_byte(_this, reg);
_this->wait_ack(_this);
_this->start(_this);
_this->send_byte(_this, ((addr << 1) | 1));
_this->wait_ack(_this);
while(len)
{
if(len == 1)*buf = _this->read_byte(_this, 0);
else *buf = _this->read_byte(_this, 1);
len--;
buf++;
}
_this->stop(_this);
return 0;
}
void new_IIC_config(iic * pObj, char _scl_port, char _sda_port, unsigned short _scl_pin, unsigned short _sda_pin)
{
if(_scl_port<'A'||_scl_port>'E'){
return ;
}
if(_sda_port<'A'||_sda_port>'E'){
return ;
}
memset(pObj, 0, sizeof(iic));
pObj->scl_port=_scl_port;
pObj->sda_port=_sda_port;
pObj->scl_pin=_scl_pin;
pObj->sda_pin=_sda_pin;
pObj->init=init;
pObj->start=start;
pObj->stop=stop;
pObj->wait_ack=wait_ack;
pObj->nack=nack;
pObj->ack=ack;
pObj->send_byte=send_byte;
pObj->read_byte=read_byte;
pObj->read_accord_to_input_length=read_accord_to_input_length;
pObj->write_accord_to_input_length=write_accord_to_input_length;
}
foc_motor
这个文件夹暂时没有用到,后期驱动电机的时候才会用。
其实上面的文件几乎都没什么需要更改的,只需要在main.c文件中调用一下就行了。
#include "main.h"
#include "Sensor.h"
#include "MagneticSensorI2C.h"
#include "stdio.h"
#include <string.h>
#include "SimpleFoc.h"
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart1;
iic i2c1;
MagneticSensor_i2c as5600;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_USART1_UART_Init(void);
int main(void)
{
float u1,u2,u3,u4,u5,u6=0;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
new_IIC_config(&i2c1,'B','B',6 ,7);
new_MagneticSensor_i2c(&as5600,AS5600_I2C);
as5600.init(&as5600,&i2c1);
printf("读取角度测试\r\n");
while (1)
{
as5600.SenSor.update(&as5600);
u1 = as5600.SenSor.getAngle(&as5600);
u2 = as5600.SenSor.getFullRotations(&as5600);
u3 = as5600.SenSor.getMechanicalAngle(&as5600);
u4 = as5600.SenSor.getPreciseAngle(&as5600);
u5 = as5600.SenSor.getSensorAngle(&as5600);
u6 = as5600.SenSor.getVelocity(&as5600);
printf("u1:%.3f - u2:%.3f - u3:%.3f - u4:%.3f - u5:%.3f - u6:%.3f\r\n",u1,u2,u3,u4,u5,u6);
HAL_Delay(200);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0){}
USART1->DR = (unsigned char) ch;
return ch;
}
#endif
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
切记每次读取需要调用update函数,否则数据只会显示上一次的数据。
实验现象
|