文章目录

  • 前言
  • 一、STM32cubeMx创建工程
  • 二、在KEIL中对IIC的配置
    • 1.在你新建的工程中导入IIC驱动文件
    • 2.增加一些需要的函数
  • 三、开始ADXL345传感器
    • 1.要学会看数据手册
    • 2.我的示例
  • 总结

废话不多说,我们直接开始

一、STM32cubeMx创建工程

(1) 、相信大家在初学stm32的时候基本都是使用st公司的标准库来学习的吧,但是如果你要学习更加深入的话个人建议你还是学习下hal库或者LL库,ST公司推出的hal库来替代原有的标准库,HAL库开始慢慢的被广大STM32开发者所接受,现在已经在实际的项目开发中大量使用,HAL库使得项目的移植变得很简介易懂,但是里面的坑也有些有....

(2)、 下面是我配置的STM32cubeMX

图1

我们打开cubeMX之后,点击新建工程之后,选择好自己用到的芯片型号,然后点击右上角那个start project 就会进入我上面图1的界面,然后根据提示依次配置好自己需要的功能,这里我用的是c8t6,我配置PB6和PB7分别作为我的驱动IIC的SCL和SDA,关于软件IIC这里就不多说什么了。

图2

时钟树我是将HCLK直接配置为72Mhz,你可以根据你所需要的功能去配置,说实话用起来挺方便的,啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈,但是要注意的一点的c8t6这里我是在图1中RCC中的HSE配置成ceramic Resonator,如果你不配置RCC中HSE的话,它默认是使用内部高速时钟RC,这样的话你无法将HCLK配置成72Mhz。

至于对project manager的设置的话相信大家看懂是没有问题的。

二、在KEIL中对IIC的配置

1.在你新建的工程中导入IIC驱动文件

(1)、iic.c文件

代码如下(示例):

#include "iic.h"
/*******************************************************************************
* 函 数 名         : IIC_Init
* 函数功能           : IIC初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);/*Configure GPIO pins : PB6 PB7 */GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);IIC_SCL=1;IIC_SDA=1;
}/*******************************************************************************
* 函 数 名         : SDA_OUT
* 函数功能           : SDA输出配置
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void SDA_OUT(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/*Configure GPIO pins : PB6 PB7 */GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}/*******************************************************************************
* 函 数 名         : SDA_IN
* 函数功能           : SDA输入配置
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void SDA_IN(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/*Configure GPIO pins : PB7 */GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}/*******************************************************************************
* 函 数 名         : IIC_Start
* 函数功能           : 产生IIC起始信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Start(void)
{SDA_OUT();     //sda线输出IIC_SDA=1;            IIC_SCL=1;Delay_us(5);IIC_SDA=0;//START:when CLK is high,DATA change form high to low Delay_us(6);IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}    /*******************************************************************************
* 函 数 名         : IIC_Stop
* 函数功能           : 产生IIC停止信号
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Stop(void)
{SDA_OUT();//sda线输出IIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highIIC_SCL=1; Delay_us(6);IIC_SDA=1;//发送I2C总线结束信号Delay_us(6);
}/*******************************************************************************
* 函 数 名         : IIC_Wait_Ack
* 函数功能           : 等待应答信号到来
* 输    入         : 无
* 输    出         : 1,接收应答失败0,接收应答成功
*******************************************************************************/
uint8_t IIC_Wait_Ack(void)
{uint8_t tempTime=0;SDA_IN();      //SDA设置为输入  IIC_SDA=1;Delay_us(1);       IIC_SCL=1;Delay_us(1);     while(READ_SDA){tempTime++;if(tempTime>250){IIC_Stop();return 1;}}IIC_SCL=0;//时钟输出0        return 0;
} /*******************************************************************************
* 函 数 名         : IIC_Ack
* 函数功能           : 产生ACK应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;Delay_us(2);IIC_SCL=1;Delay_us(5);IIC_SCL=0;
}/*******************************************************************************
* 函 数 名         : IIC_NAck
* 函数功能           : 产生NACK非应答
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void IIC_NAck(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=1;Delay_us(2);IIC_SCL=1;Delay_us(5);IIC_SCL=0;
}    /*******************************************************************************
* 函 数 名         : IIC_Send_Byte
* 函数功能           : IIC发送一个字节
* 输    入         : txd:发送一个字节
* 输    出         : 无
*******************************************************************************/
void IIC_Send_Byte(uint8_t txd)
{                        uint8_t t;   SDA_OUT();         IIC_SCL=0;//拉低时钟开始数据传输for(t=0;t<8;t++){              if((txd&0x80)>0) //0x80  1000 0000IIC_SDA=1;elseIIC_SDA=0;txd<<=1;       Delay_us(2);   //三个延时是必须的IIC_SCL=1;Delay_us(2); IIC_SCL=0;    Delay_us(2);}
} /*******************************************************************************
* 函 数 名         : IIC_Read_Byte
* 函数功能           : IIC读一个字节
* 输    入         : ack=1时,发送ACK,ack=0,发送nACK
* 输    出         : 应答或非应答
*******************************************************************************/
uint8_t IIC_Read_Byte(uint8_t ack)
{uint8_t 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();//发送nACKelseIIC_Ack(); //发送ACK   return receive;
}

(2)、iic.h文件

代码示例如下:

#ifndef _iic_H
#define _iic_H#include "system.h"
#include "stm32f103xb.h"
//IO操作函数
#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA
#define READ_SDA   PBin(7)  //输入SDA//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口
void IIC_Start(void);               //发送IIC开始信号
void IIC_Stop(void);                //发送IIC停止信号
void IIC_Send_Byte(uint8_t txd);            //IIC发送一个字节
uint8_t IIC_Read_Byte(uint8_t ack);//IIC读取一个字节
uint8_t IIC_Wait_Ack(void);                 //IIC等待ACK信号
void IIC_Ack(void);                 //IIC发送ACK信号
void IIC_NAck(void);                //IIC不发送ACK信号#endif

这里是iic的软件驱动,网上其实有很多类似的软件驱动iic的例子,大家如果感兴趣的话开头去看看

2.增加一些需要的函数

配置SDA的引脚号输入和输出感觉有点麻烦,在这里我用了位带操作

代码如下(示例):

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    #define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 //IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

当然如果你不嫌麻烦的话你也可以直接用别的来配置。

三、开始ADXL345传感器

ADXL345是一款小而薄的超低功耗3轴加速度计,分辨率 高(13位),测量范围达± 16g。数字输出数据为16位二进制 补码格式,可通过SPI(3线或4线)或I2C数字接口访问。 ADXL345非常适合移动设备应用。它可以在倾斜检测应用 中测量静态重力加速度,还可以测量运动或冲击导致的动
态加速度。其高分辨率(3.9mg/LSB),能够测量不到1.0°的 倾斜角度变化。

ADXL345主要用在对一些特殊活动的检测,用它来做个计步器啥的虽然说有点偏差,但是也大差不差啦。

1.要学会看数据手册

相信很多人跟我一样拿到一些传感器之后第一时间就是上网去找找有没有别人跟自己用同样的传感器做东西吧,啊哈哈哈哈哈,我想说明的是虽然这种方式可取,但是对于别人的东西可能用到的跟你不一样,个人建议,拿到资料之后,最后是找官方的例子结合数据手册来看,学会看数据手册是一件很重要的事情,数据手册里面包含的东西可能比你去网上找的别人理解的还要多,所以如果你是在做项目开发的话,我个人的建议是先仔细看几遍数据手册,以便来得到你想到的功能框架,看懂了数据手册你才算真正的入门这个传感器。

2.我的示例

接下来我会用我的例子来让大家看看,很多东西都可以从数据手册中得来的

(1)我先将ADXL345.h的文件展示出来

里面包含了一些结构体定义以及ADXL345的寄存器地址等等

#ifndef _adxl345_H
#define _adxl345_H#include "system.h"#define DEVICE_ID        0X00    //器件ID,0XE5
#define THRESH_TAP      0X1D    //敲击阀值
#define OFSX            0X1E
#define OFSY            0X1F
#define OFSZ            0X20
#define DUR             0X21
#define Latent          0X22
#define Window          0X23
#define THRESH_ACK      0X24
#define THRESH_INACT    0X25
#define TIME_INACT      0X26
#define ACT_INACT_CTL   0X27
#define THRESH_FF       0X28
#define TIME_FF         0X29
#define TAP_AXES        0X2A
#define ACT_TAP_STATUS  0X2B
#define BW_RATE         0X2C
#define POWER_CTL       0X2D #define INT_ENABLE     0X2E
#define INT_MAP         0X2F
#define INT_SOURCE      0X30
#define DATA_FORMAT     0X31
#define DATA_X0         0X32
#define DATA_X1         0X33
#define DATA_Y0         0X34
#define DATA_Y1         0X35
#define DATA_Z0         0X36
#define DATA_Z1         0X37
#define FIFO_CTL        0X38
#define FIFO_STATUS     0X39typedef struct {short x;short y;short z;
}axis_info_t;typedef struct {short x;short y;short z;
}sample_xyz;
//如果SD0(12脚)接地,ADXL地址为0X53(不包含最低位).
//如果SD0接V3.3,则ADXL地址为0X1D(不包含最低位).
//这里我的接法是CS和SD0接V3.3,所以转为读写地址后,为0X3B和0X3A(如果接GND,则为0XA7和0XA6)
//可以根据具体情况来配置
#define ADXL_READ    0X3B
#define ADXL_WRITE   0X3Auint8_t ADXL345_Init(void);                                //初始化ADXL345
void ADXL345_WR_Reg(uint8_t addr,uint8_t val);              //写ADXL345寄存器
uint8_t ADXL345_RD_Reg(uint8_t addr);                           //读ADXL345寄存器
void ADXL345_RD_XYZ(short *x,short *y,short *z);    //读取一次值
void ADXL345_RD_Avval(short *x,short *y,short *z);  //读取平均值
void ADXL345_AUTO_Adjust(char *xval,char *yval,char *zval);//自动校准
void ADXL345_Read_Average(short *x,short *y,short *z,uint8_t times);//连续读取times次,取平均
short ADXL345_Get_Angle(float x,float y,float z,uint8_t dir);
void Pedometer_Algorithm(axis_info_t *sample);
void Fall_Detection(sample_xyz *data);
void data_pros(void);
#endif

(2)ADXL345_WR_Reg:写ADXL345寄存器

addr:是寄存器的地址 val:是要写入寄存器的值

void ADXL345_WR_Reg(uint8_t addr,uint8_t val)
{IIC_Start();                IIC_Send_Byte(ADXL_WRITE);         //发送写器件指令    IIC_Wait_Ack();       IIC_Send_Byte(addr);             //发送寄存器地址IIC_Wait_Ack();                                                       IIC_Send_Byte(val);          //发送值                      IIC_Wait_Ack();                     IIC_Stop();                      //产生一个停止条件
} 

(3)ADXL345_RD_Reg:读ADXL345寄存器

addr:同上 返回值:返回读到的值

uint8_t ADXL345_RD_Reg(uint8_t addr)
{uint8_t temp=0;        IIC_Start();                IIC_Send_Byte(ADXL_WRITE); //发送写器件指令    temp=IIC_Wait_Ack();     IIC_Send_Byte(addr);         //发送寄存器地址temp=IIC_Wait_Ack();                                                     IIC_Start();                 //重新启动IIC_Send_Byte(ADXL_READ); //发送读器件指令    temp=IIC_Wait_Ack();     temp=IIC_Read_Byte(0);      //读取一个字节,不继续再读,发送NAK               IIC_Stop();                  //产生一个停止条件      return temp;                //返回读到的值
} 

(4)ADXL345_Init:初始化ADXL345

成功返回0 失败返回1

uint8_t ADXL345_Init(void)
{                 IIC_Init();                           //初始化IIC总线  if(ADXL345_RD_Reg(DEVICE_ID)==0XE5)   //读取器件ID{  ADXL345_WR_Reg(DATA_FORMAT,0X2B);    //低电平中断输出,13位全分辨率,输出数据右对齐,16g量程 ADXL345_WR_Reg(BW_RATE,0x09);       //数据输出速度为100HzADXL345_WR_Reg(POWER_CTL,0x28);       //链接使能,测量模式ADXL345_WR_Reg(INT_ENABLE,0x00); //不使用中断      ADXL345_WR_Reg(OFSX,0x00);ADXL345_WR_Reg(OFSY,0x00);ADXL345_WR_Reg(OFSZ,0x00); return 0;}          return 1;
} 

(5)ADXL345_RD_XYZ:读取x,y,z三个轴的数据

void ADXL345_RD_XYZ(short *x,short *y,short *z)
{uint8_t buf[6];uint8_t i;IIC_Start();                   IIC_Send_Byte(ADXL_WRITE); //发送写器件指令    IIC_Wait_Ack();       IIC_Send_Byte(0x32);         //发送寄存器地址(数据缓存的起始地址为0X32)IIC_Wait_Ack();                                                       IIC_Start();                 //重新启动IIC_Send_Byte(ADXL_READ); //发送读器件指令IIC_Wait_Ack();for(i=0;i<6;i++){if(i==5)buf[i]=IIC_Read_Byte(0);//读取一个字节,不继续再读,发送NACK  else buf[i]=IIC_Read_Byte(1); //读取一个字节,继续读,发送ACK }                   IIC_Stop();                  //产生一个停止条件*x=(short)(((uint16_t)buf[1]<<8)+buf[0]);         *y=(short)(((uint16_t)buf[3]<<8)+buf[2]);       *z=(short)(((uint16_t)buf[5]<<8)+buf[4]);
}

(6)ADXL345_Read_Average:读取ADXL345的数据times次,再取平均

这种方式能够有效将数据进行滤波,去除掉那些突现的尖峰值

void ADXL345_Read_Average(short *x,short *y,short *z,uint8_t times)
{uint8_t i;short tx,ty,tz;*x=0;*y=0;*z=0;if(times)//读取次数不为0{for(i=0;i<times;i++)//连续读取times次{ADXL345_RD_XYZ(&tx,&ty,&tz);*x+=tx;*y+=ty;*z+=tz;Delay_ms(5);}*x/=times;*y/=times;*z/=times;}
}

(7)ADXL345_Get_Angle:通过公式计算x,y,z方向的加速度分量后得出三个方面的角度

short ADXL345_Get_Angle(float x,float y,float z,uint8_t dir)
{float temp;float res=0;switch(dir){case 0://与自然Z轴的角度temp=sqrt((x*x+y*y))/z;res=atan(temp);break;case 1://与自然X轴的角度temp=x/sqrt((y*y+z*z));res=atan(temp);break;case 2://与自然Y轴的角度temp=y/sqrt((x*x+z*z));res=atan(temp);break;}return res*180/3.14;
}

到这里ADXL345基本功能实现,能够得出三个方向的加速度以及三个方向的关于原来方向的偏移角度

注意:

1、 在读取ADXL345寄存器时,要注意读取的是8位字节的数据,所以你要依次将其读出,然后将高八位有效值低八位有效值相加

2、相加后得到的x,y,z 的值是它们的LSB值,如果你设置的是全分辨率的话,就将得到的数据与3.9mg相乘,这样子得到的数据就是它们加速度mg值

3、根据自己的需要配置ADXL345的输出速率

如图:

这里我选择的是输出数据速率为50hz 即每20毫秒输出一组数据

4、对于偏移校准问题,ADXL345的数据手册里面也给出了相应的解决方法

xval=-offx/4;
    yval=-offy/4;
    zval=-(offz-256)/4;

其中offx,offy,offz分别表示原来的加速度值

总结

对于ADXL345的使用我还只是摸到了一点门槛,对于中断方面的使用我还没有摸透,有些中断用得了,有些中断用不了,啊哈哈哈哈哈,之后我会继续搞下ADXL345的中断。

本文有什么不足的请各位指定一二。

1、STM32通过软件IIC连接ADXL345(ADXL345使用遇到的一些坑)相关推荐

  1. 基于STM32的软件IIC实现

    嵌入式_基于STM32的软件IIC实现 本文是基于STM32标准库的IIC实现,并再此基础上实现了AT24C02的读写,关于IIC的原理简介请参见上篇IIC协议理解, 文章目录 嵌入式_基于STM32 ...

  2. STM32基于软件模拟IIC进行AHT21B温湿度采集

    STM32基于软件模拟IIC进行AHT21B温湿度采集 一. IIC简介 1.1 IIC简介 1.2 实现方式 1.3 实现方式对比 二. AHT21B简介 2.1 简介 2.2 产品特点 2.3 外 ...

  3. STM32使用IIC总线通讯协议在OLED屏幕上显示字符串、汉字、单总线获取DHT11模块温湿度并通过IIC显示到屏幕(软件IIC)

    参考:基于stm32软件IIC的oled显示温湿度 作者:ZPZ DayUp 发布时间: 2021-07-25 20:52:43 网址:https://blog.csdn.net/m0_5619768 ...

  4. STM32 驱动 GY-302 光照传感器 BH1750 模块(软件IIC与硬件IIC驱动)

    1.特别说明 ​ 要是不想看原理和过程,直接下拉找代码吧,都是测试过的,很稳定,有硬件I2C驱动的,也有软件模拟I2C驱动的,基于STM32F103系列和STM32F4系列实现,基于标准库实现,条理清 ...

  5. 【STM32】标准库与HAL库对照学习教程十三--软件IIC控制AT24C02

    [STM32]标准库与HAL库对照学习教程十三--软件IIC控制AT24C02 一.前言 二.准备工作 三.AT24C02(EEPROM)介绍 1.AT24C02简介 2.引脚功能 3.设备地址 四. ...

  6. 15. STM32——软件IIC驱动OLED屏幕显示字符、字符串、数字、汉字

    STM32--软件IIC驱动OLED屏幕显示 OLED屏幕 写命令 写内容 对OLED写入一个字节 设置光标 启动OLED 关闭OLED 全屏填充(清屏) 显示字符 显示字符串 获取次方 显示数字 显 ...

  7. 【STM32-I2C学习总结】STM32:硬件-IIC详解 , 固件库编程 , 手把手教你实现IIC

    STM32:硬件-IIC详解 , 固件库编程 , 手把手教你实现IIC 一 .I2C物理层 二.协议层 1.I2C基本读写过程 (1)主机写数据到从机 (2)主机由从机中读数据 (3)I2C 通讯复合 ...

  8. SLAM导航机器人零基础实战系列:(四)差分底盘设计——2.stm32主控软件设计

    SLAM导航机器人零基础实战系列:(四)差分底盘设计--2.stm32主控软件设计 摘要 运动底盘是移动机器人的重要组成部分,不像激光雷达.IMU.麦克风.音响.摄像头这些通用部件可以直接买到,很难买 ...

  9. STM32F4软件IIC的使用

    1.开发环境 2.说明 3.F4和F1软件IIC区别 GPIO初始化区别 us级延时区别 总结 1.开发环境:硬件:STM32F407IGH6开发板 任意可使用IIC通讯协议传感器 软件:Keil C ...

  10. STM32 HAL库IIC驱动

    1. STM32上IIC的一些争议 关于STM32的IIC驱动,网上有很多争论,究竟是使用STM32自带的硬件IIC还是用IO口和软件模拟IIC呢?下面这个图形象展示了这些争论.总结一些:ST为了规避 ...

最新文章

  1. android o测试版,一加手机可升级!谷歌已正式推送Android O测试版系统
  2. php yaf smarty,Yaf 结合用户自定义的视图(模板)引擎Smarty(Yaf + Smarty)
  3. 抽象工厂模式设计模式_21世纪的设计模式:抽象工厂模式
  4. apache hive_通过6个简单的步骤在Windows上运行Apache Hive
  5. jOOQ与Hibernate:何时选择哪个
  6. python移位操作困惑
  7. 《Reids 设计与实现》第七章 RDB 持久化
  8. php实现ppt样式效果源码,jQuery移动端和桌面设备的轻量级幻灯片特效源码
  9. 未来PCB行业互联网+发展趋势
  10. 21.5 英寸 iMac 供应减少:是新品发布的节奏吗?
  11. iOS 刘海屏 隐藏横条 home键
  12. 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题2---CMAKE配置问题
  13. 计算机软件行业各职位英文缩写
  14. 怎样清理计算机c盘东西,电脑c盘满了怎么清理
  15. 设置C++缺省源的方法(DEV C++)
  16. 「网络流 24 题」火星探险问题。
  17. 【Monkey Run】Excel编程 VBA
  18. Louvain 算法
  19. 5y计算机应用选择题答案,2016年电大网考计算机应用基础统考试题模拟真题及答案 含小抄复习资料推荐.docx...
  20. (35)代码优化以后的运行结果

热门文章

  1. 2012年全国中等职业学校计算机类专业课程创新杯教师说课,2012年全国中等职业学校建筑类专业创新杯教师教学设计和说课大赛获.doc...
  2. 习题5.4 找出4*5矩阵中值最小和最大元素,并分别输出其值及所在的行号和列号。
  3. Python使用turtle绘图中设置小乌龟(画笔)旋转的角度turtle.setheading()
  4. 大数据技术基础学习总结
  5. 代码实现HelloMeituanCom转换为hello.meituan.com
  6. hyperlink的学习
  7. SpringBoot MultipartResolver的坑
  8. C++根据旋转轴和角度求旋转矩阵
  9. redis哨兵集群、docker入门
  10. 捋一捋字符串和字节序列的关系