第七周嵌入式实验

本文介绍了如何在STM32中使用I2C协议,包括硬件I2C和软件I2C的工作原理,并详细讲解了AHT20温湿度传感器的硬件连接和代码实现,以及如何将数据上传至上位机。此外,还展示了如何通过OLED屏显示温湿度和长字符,涉及OLED屏显的硬件连接及代码移植。
摘要由CSDN通过智能技术生成

一、I2C协议和AHT20温湿度发送上位机

1、了解I2C协议

什么是I2C协议
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。

I2C 协议的物理层和协议层
①物理层
I2C是一个支持设备的总线。可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。对于I2C 总线,只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线(SCL)。
②协议层

主要是定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等。
I2C的两种方式——硬件I2C和软件I2C
①硬件I2C
直接利用 STM32 芯片中的硬件 I2C 外设。

硬件I2C的使用
只要配置好对应的寄存器,外设就会产生标准串口协议的时序。在初始化好 I2C 外设后,只需要把某寄存器位置 1,此时外设就会控制对应的 SCL 及 SDA 线自动产生 I2C 起始信号,不需要内核直接控制引脚的电平。

②软件I2C
直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平,从而模拟I2C。

软件I2C的使用
需要在控制产生 I2C 的起始信号时,控制作为 SCL 线的 GPIO 引脚输出高电平,然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至低电平的切换,最后再控制SCL 线切换为低电平,这样就输出了一个标准的 I2C 起始信号。

③两者的差别
硬件 I2C 直接使用外设来控制引脚,可以减轻 CPU 的负担。不过使用硬件I2C 时必须使用某些固定的引脚作为 SCL 和 SDA,软件模拟 I2C 则可以使用任意 GPIO 引脚,相对比较灵活。对于硬件I2C用法比较复杂,软件I2C的流程更清楚一些。如果要详细了解I2C的协议,使用软件I2C可能更好的理解这个过程。在使用I2C过程,硬件I2C可能通信更加快,更加稳定。

2、AHT20温湿度传感器上传上位机

硬件连接

在这里插入图片描述
AHT20的SCL,GND,SDA,VCC分别对应B6,GND,B7,5V

代码

在固件库版的空白工程上进行添加修改代码
主函数

#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"


int main(void)
{
   	
	delay_init();     //?óê±oˉêy3?ê??ˉ	  
	uart_init(115200);	 //′??ú3?ê??ˉ?a115200
	IIC_Init();
		while(1)
	{
   
		printf("温度湿度显示");
		read_AHT20_once();
		delay_ms(1500);
  }
}

添加工程文件
usart.c

#include "sys.h"
#include "usart.h"


//STM32F103o?D?°?ày3ì
//?aoˉêy°?±?ày3ì
/********** mcudev.taobao.com 3??·  ********/


// 	 
//è?1?ê1ó?ucos,?ò°üà¨????μ?í·???t?′?é.
#if SYSTEM_SUPPORT_UCOS
#include "includes.h"					//ucos ê1ó?	  
#endif
//	 
//STM32?a·¢°?
//′??ú13?ê??ˉ		   

// 	  
 

//
//?óè?ò???′ú??,?§3?printfoˉêy,??2?Dèòa????use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//±ê×??aDèòaμ??§3?oˉêy                 
struct __FILE 
{
    
	int handle; 

}; 

FILE __stdout;       
//?¨ò?_sys_exit()ò?±ü?aê1ó?°??÷?ú?£ê?    
void _sys_exit(int x) 
{
    
	x = x; 
} 
//???¨ò?fputcoˉêy 
int fputc(int ch, FILE *f)
{
         
	while((USART1->SR&0X40)==0);//?-?··¢?í,?±μ?·¢?ííê±?   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

/*ê1ó?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?ê1?üá??óê?
//′??ú1?D??·t??3ìDò
//×¢òa,?áè?USARTx->SR?ü±ü?a?a??????μ?′í?ó   	
u8 USART_RX_BUF[USART_REC_LEN];     //?óê??o3?,×?′óUSART_REC_LEN??×??ú.
//?óê?×′ì?
//bit15£?	?óê?íê3é±ê??
//bit14£?	?óê?μ?0x0d
//bit13~0£?	?óê?μ?μ?óDD§×??úêy??
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);	//ê1?ü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;	//?′ó?í?íìê?3?
    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í¨μàê1?ü
	NVIC_Init(&NVIC_InitStructure);	//?ù?Y???¨μ?2?êy3?ê??ˉVIC??′??÷
  
   //USART 3?ê??ˉéè??

	USART_InitStructure.USART_BaudRate = bound;//ò?°?éè???a9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×?3¤?a8??êy?Y??ê?
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//ò???í£?1??
	USART_InitStructure.USART_Parity = USART_Parity_No;//?T????D£?é??
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//?Tó2?têy?Yá÷????
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//ê?·¢?£ê?

    USART_Init(USART1, &USART_InitStructure); //3?ê??ˉ′??ú
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//?a???D??
    USART_Cmd(USART1, ENABLE);                    //ê1?ü′??ú 

}



void USART1_IRQHandler(void)                	//′??ú1?D??·t??3ìDò
	{
   
	u8 Res;
#ifdef OS_TICKS_PER_SEC	 	//è?1?ê±?ó?ú??êy?¨ò?á?,?μ?÷òaê1ó?ucosIIá?.
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //?óê??D??(?óê?μ?μ?êy?Y±?D?ê?0x0d 0x0a?á?2)
		{
   
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//?áè??óê?μ?μ?êy?Y
		
		if((USART_RX_STA&0x8000)==0)//?óê??′íê3é
			{
   
			if(USART_RX_STA&0x4000)//?óê?μ?á?0x0d
				{
   
				if(Res!=0x0a)USART_RX_STA=0;//?óê?′í?ó,??D??aê?
				else USART_RX_STA|=0x8000;	//?óê?íê3éá? 
				}
			else //?1??ê?μ?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;//?óê?êy?Y′í?ó,??D??aê??óê?	  
					}		 
				}
			}   		 
     } 
#ifdef OS_TICKS_PER_SEC	 	//è?1?ê±?ó?ú??êy?¨ò?á?,?μ?÷òaê1ó?ucosIIá?.
	OSIntExit();  											 
#endif
} 
#endif	


usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" 

//STM32F103o?D?°?ày3ì
//?aoˉêy°?±?ày3ì
/********** mcudev.taobao.com 3??·  ********/

//	 
//STM32?a·¢°?
//′??ú13?ê??ˉ		   

#define USART_REC_LEN  			200  	//?¨ò?×?′ó?óê?×??úêy 200
#define EN_USART1_RX 			1		    //ê1?ü£¨1£?/???1£¨0£?′??ú1?óê?
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //?óê??o3?,×?′óUSART_REC_LEN??×??ú.??×??ú?a??DD·? 
extern u16 USART_RX_STA;         		//?óê?×′ì?±ê??	
//è?1???′??ú?D???óê?£???2?òa×¢êíò???oê?¨ò?
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 ;   //í?íìê?3?
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
 
	IIC_SCL=1;
	IIC_SDA=1;
 
}
//2úéúIIC?eê?D?o?
void IIC_Start(void)
{
   
	SDA_OUT();     //sda??ê?3?
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//?ˉ×?I2C×ü??£?×?±?·¢?í?ò?óê?êy?Y 
}	  
//2úéúIICí£?1D?o?
void IIC_Stop(void)
{
   
	SDA_OUT();//sda??ê?3?
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//·¢?íI2C×ü???áê?D?o?
	delay_us(4);							   	
}
//μè′yó|′eD?o?μ?à′
//·μ???μ£o1£??óê?ó|′e꧰ü
//        0£??óê?ó|′e3é1|
u8 IIC_Wait_Ack(void)
{
   
	u8 ucErrTime=0;
	SDA_IN();      //SDAéè???aê?è?  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
   
		ucErrTime++;
		if(ucErrTime>250)
		{
   
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//ê±?óê?3?0 	   
	return 0;  
} 
//2úéúACKó|′e
void IIC_Ack(void)
{
   
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//2?2úéúACKó|′e		    
void IIC_NAck(void)
{
   
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC·¢?íò???×??ú
//·μ??′ó?úóD?Tó|′e
//1£?óDó|′e
//0£??Tó|′e			  
void IIC_Send_Byte(u8 txd)
{
                           
    u8 t;   
		SDA_OUT(); 	    
    IIC_SCL=0;//à-μíê±?ó?aê?êy?Y′?ê?
    for(t=0;t<8;t++)
    {
                 
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //??TEA5767?aèy???óê±??ê?±?D?μ?
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//?á1??×??ú£?ack=1ê±£?·¢?íACK£?ack=0£?·¢?ínACK   
u8 IIC_Read_Byte(unsigned char ack)
{
   
	unsigned char i,receive=0;
	SDA_IN();//SDAéè???aê?è?
  for(i=0;i<8;i++ )
	
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值