一、I2C协议
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。
1、I2C的分类
(1)软件I2C
软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。软件I2C 是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。
(2)硬件I2C
硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的;硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
2、区别
(1)看底层配置,比如IO口配置,如果配置了IO口的功能(IIC功能)那就是固件IIC,否则就是模拟 。
(2)看IIC写函数,看里面有没有调用现成的函数或者给某个寄存器赋值,如果有,则肯定是固件IIC功能,没有的话肯定是数据一个bit一个bit模拟发生送的,肯定用到了循环,则为模拟。
(3)根据代码量判断,模拟的代码量肯定比固件的要大。
①硬件IIC用法比较复杂,模拟IIC的流程更清楚一些。
②硬件IIC速度比模拟快,并且可以用DMA
③模拟IIC可以在任何管脚上,而硬件只能在固定管脚上。
(4)软件I2C是程序员使用程序控制SCL,SDA线输出高低电平,模拟I2C协议的时序。一般较硬件i2c稳定,但是程序较为繁琐,但不难。
(5)硬件I2C程序员只要调用I2C的控制函数即可,不用直接的去控制SCL,SDA高低电平的输出。但是有些单片机的硬件I2C不太稳定,调试问题较多。
二、基于I2C硬件协议的AHT20温湿度传感器的数据采集
1、AHT20
AHT20,新一代温湿度传感器在尺寸与智能 方面建立了新的标准:它嵌入了适于回流焊的双列扁平无引脚SMD 封装,底面 3 x 3mm ,高度1.0mm。传感器输出经过标定的数字信 号,标准 I2C 格式。
AHT20 配有一个全新设计的 ASIC专用芯片、 一个经过改进的MEMS半导体电容式湿度传感 元件和一个标准的片上温度传感元件,其性 能已经大大提升甚至超出了前一代传感器的 可靠性水平,新一代温湿度传感器,经过改 进使其在恶劣环境下的性能更稳定。 每一个传感器都经过校准和测试,在产品表 面印有产品批号。由于对传感器做了改良和 微型化改进,因此它的性价比更高,并且最 终所有设备都将得益于尖端的节能运行模式。
2、基本参数
3、AHT20 - IC管脚定义
4、程序实现AHT20温湿度传感器的数据采集
(1)通过串口通信的源代码进行修改
我是用的野火的资料找的
(2)把main.c内容修改为如下程序
#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
int main(void)
{
delay_init(); //ÑÓʱº¯Êý³õʼ»¯
uart_init(115200); //´®¿Ú³õʼ»¯Îª115200
IIC_Init();
while(1)
{
printf("¿ªÊ¼²âÁ¿£¬ÇëÉԵȣº");
read_AHT20_once();
delay_ms(1500);
}
}
(3)新建空白页,把以下程序粘贴进去,每个程序单独粘贴,然后保存到相应的项目文件的User中
usart.c
#include "sys.h"
#include "usart.h"
//STM32F103ºËÐÄ°åÀý³Ì
//¿âº¯Êý°æ±¾Àý³Ì
/********** mcudev.taobao.com ³öÆ· ********/
//
//Èç¹ûʹÓÃucos,Ôò°üÀ¨ÏÂÃæµÄÍ·Îļþ¼´¿É.
#if SYSTEM_SUPPORT_UCOS
#include "includes.h" //ucos ʹÓÃ
#endif
//
//STM32¿ª·¢°å
//´®¿Ú1³õʼ»¯
//
//
//¼ÓÈëÒÔÏ´úÂë,Ö§³Öprintfº¯Êý,¶ø²»ÐèҪѡÔñuse MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//±ê×¼¿âÐèÒªµÄÖ§³Öº¯Êý
struct __FILE
{
int handle;
};
FILE __stdout;
//¶¨Òå_sys_exit()ÒÔ±ÜÃâʹÓðëÖ÷»úģʽ
void _sys_exit(int x)
{
x = x;
}
//Öض¨Òåfputcº¯Êý
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//Ñ»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï
USART1->DR = (u8) ch;
return ch;
}
#endif
/*ʹÓÃmicroLibµÄ·½·¨*/
/*
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (uint8_t) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}
return ch;
}
int GetKey (void) {
while (!(USART1->SR & USART_FLAG_RXNE));
return ((int)(USART1->DR & 0x1FF));
}
*/
#if EN_USART1_RX //Èç¹ûʹÄÜÁ˽ÓÊÕ
//´®¿Ú1ÖжϷþÎñ³ÌÐò
//×¢Òâ,¶ÁÈ¡USARTx->SRÄܱÜÃâĪÃûÆäÃîµÄ´íÎó
u8 USART_RX_BUF[USART_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.
//½ÓÊÕ״̬
//bit15£¬ ½ÓÊÕÍê³É±êÖ¾
//bit14£¬ ½ÓÊÕµ½0x0d
//bit13~0£¬ ½ÓÊÕµ½µÄÓÐЧ×Ö½ÚÊýÄ¿
u16 USART_RX_STA=0; //½ÓÊÕ״̬±ê¼Ç
void uart_init(u32 bound){
//GPIO¶Ë¿ÚÉèÖÃ
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //ʹÄÜUSART1£¬GPIOAʱÖÓ
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë
GPIO_Init(GPIOA, &GPIO_InitStructure);
//Usart1 NVIC ÅäÖÃ
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//ÇÀÕ¼ÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //×ÓÓÅÏȼ¶3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ
NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷
//USART ³õʼ»¯ÉèÖÃ
USART_InitStructure.USART_BaudRate = bound;//Ò»°ãÉèÖÃΪ9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ
USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ
USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //ÊÕ·¢Ä£Ê½
USART_Init(USART1, &USART_InitStructure); //³õʼ»¯´®¿Ú
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//¿ªÆôÖжÏ
USART_Cmd(USART1, ENABLE); //ʹÄÜ´®¿Ú
}
void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò
{
u8 Res;
#ifdef OS_TICKS_PER_SEC //Èç¹ûʱÖÓ½ÚÅÄÊý¶¨ÒåÁË,˵Ã÷ҪʹÓÃucosIIÁË.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É
{
if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼
else USART_RX_STA|=0x8000; //½ÓÊÕÍê³ÉÁË
}
else //»¹Ã»ÊÕµ½0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ
}
}
}
}
#ifdef OS_TICKS_PER_SEC //Èç¹ûʱÖÓ½ÚÅÄÊý¶¨ÒåÁË,˵Ã÷ҪʹÓÃucosIIÁË.
OSIntExit();
#endif
}
#endif
usart.h
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
//STM32F103ºËÐÄ°åÀý³Ì
//¿âº¯Êý°æ±¾Àý³Ì
/********** mcudev.taobao.com ³öÆ· ********/
//
//STM32¿ª·¢°å
//´®¿Ú1³õʼ»¯
#define USART_REC_LEN 200 //¶¨Òå×î´ó½ÓÊÕ×Ö½ÚÊý 200
#define EN_USART1_RX 1 //ʹÄÜ£¨1£©/½ûÖ¹£¨0£©´®¿Ú1½ÓÊÕ
extern u8 USART_RX_BUF[USART_REC_LEN]; //½ÓÊÕ»º³å,×î´óUSART_REC_LEN¸ö×Ö½Ú.Ä©×Ö½ÚΪ»»Ðзû
extern u16 USART_RX_STA; //½ÓÊÕ״̬±ê¼Ç
//Èç¹ûÏë´®¿ÚÖжϽÓÊÕ£¬Ç벻ҪעÊÍÒÔϺ궨Òå
void uart_init(u32 bound);
#endif
bsp_i2c.c
#include "bsp_i2c.h"
#include "delay.h"
uint8_t ack_status=0;
uint8_t readByte[6];
uint8_t AHT20_status=0;
uint32_t H1=0; //Humility
uint32_t T1=0; //Temperature
uint8_t AHT20_OutData[4];
uint8_t AHT20sendOutData[10] = {
0xFA, 0x06, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
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