OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32/FPGA开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...
查看: 923|回复: 6

求一个AVR单片机温湿度模块(IIC)的例程。

[复制链接]

  离线 

8

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
147
金钱
147
注册时间
2017-3-8
在线时间
35 小时
发表于 2017-6-12 15:53:44 | 显示全部楼层 |阅读模式
10金钱
求一个例程,使用IIC通信,模块是AM2322B。DHT11之类的也可以!感谢

最佳答案

查看完整内容[请看2#楼]

自己写的,还没测试,希望你们也能用得上。[mw_shl_code=c,true]//模拟IIC #define SDA_PIN PINC4//数据线pc4 #define SCL_PIN PINC5//时钟线pc5 #define SDA_OUT DDRC|=(1
回复

使用道具 举报

  离线 

8

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
147
金钱
147
注册时间
2017-3-8
在线时间
35 小时
 楼主| 发表于 2017-6-12 15:53:45 | 显示全部楼层
自己写的,还没测试,希望你们也能用得上。
[C] 纯文本查看 复制代码
//模拟IIC
#define SDA_PIN PINC4//数据线pc4
#define SCL_PIN PINC5//时钟线pc5
#define SDA_OUT DDRC|=(1<<SDA_PIN)//数据线输出
#define SDA_IN DDRC&=~(1<<SDA_PIN)//数据线输入
#define SDA_LOW PORTC&=~(1<<SDA_PIN)//数据线拉低
#define SDA_HIGH PORTC|=(1<<SDA_PIN)//数据线拉高
#define SDA_READ PINC&=(1<<SDA_PIN)//读数据线电平值

#define SCL_OUT DDRC|=(1<<SCL_PIN)//时钟线输出
#define SCL_IN DDRC&=~(1<<SCL_PIN)//时钟线输入
#define SCL_LOW PORTC&=~(1<<SCL_PIN)//时钟线拉低
#define SCL_HIGH PORTC|=(1<<SCL_PIN)//时钟线拉高
#define SCL_READ PINC&=(1<<SCL_PIN)//读时钟线电平值
//定义器件地址,全局变量
#define IIC_Address 0xB8
#define IIC_RX_Len 15
unsigned char IIC_TX_Buffer[]={0x03,0x00,0x04};//读温湿度命令
unsigned char IIC_RX_Buffer[IIC_RX_Len]={0x00};//读取到的温湿度
unsigned char Error_Mess[]={"error"};
unsigned char WR_Flag;
//IIC相关函数
void IIC_Init(void);//IIC初始化
void IIC_Start(void);//IIC起始信号
void IIC_Stop(void);//IIC停止信号
void IIC_ACK(void);//主机应答
void IIC_NACK(void);//主机非应答
unsigned char  IIC_Wait_NACK(void);//等待应答信号
void IIC_Send_Byte(unsigned char data);//IIC发送一个字节 data:要发送的数据
unsigned char IIC_Read_Byte(unsigned char ack);//读一个字节,ack=1时,发送ACK,ack=0时,发送NACK;
//AM2322相关函数
void Waken(void);//唤醒芯片
void Clear_Data(void);//清空接收缓冲区数据
unsigned int CRC16(unsigned char *ptr,unsigned char len);//计算CRC校验码
/**ptr:接收到数据的首地址;len:数据的长度*/
unsigned char CheckCRC(unsigned char *ptr,unsigned char len);//检验CRC校验码是否正确
/**ptr:接收到数据的首地址;len:数据的长度*/
unsigned char WriteNByte(unsigned char sla,unsigned char *s,unsigned char n);//写入数据,即发送开始命令
/*add:器件地址;*s:数据首地址;n:数据个数*/
unsigned char ReadNByte(unsigned char sla,unsigned char *p,unsigned char n);//读数据,即读温湿度值
/*add:器件地址;*p:保存数据首地址;n:数据个数*/
void press_AM2322_Data(void);//温湿度数据处理

void IIC_Init(void)
{
	//设置输出
	SDA_OUT;
	SCL_OUT;
	//输出高电平
	SDA_HIGH;
	SCL_HIGH;
}
void IIC_Start(void)
{
	//起始条件,SCL为高时,SDA产生一个下降沿
	SDA_OUT;
	SDA_HIGH;
	SCL_HIGH;
	_delay_us(10);
	SDA_LOW;
	_delay_us(10);
	SCL_LOW;
}
void IIC_Stop(void)
{
	//停止条件,SCL为高电平时,SDA产生一个上升沿
	SDA_OUT;
	SDA_LOW;
	SCL_LOW;
	_delay_us(10);
	SCL_HIGH;
	_delay_us(10);
	SDA_HIGH;
	_delay_us(10);
}
void IIC_ACK(void)
{
	//主机应答,SCL为高电平时,SDA始终为低电平
	SCL_LOW;
	SDA_OUT;
	SDA_LOW;
	_delay_us(10);
	SCL_HIGH;
	_delay_us(10);
	SCL_LOW;
}
void IIC_NACK(void)
{
	//主机非应答,SCL为高电平时,SDA始终为高电平
	SCL_LOW;
	SDA_OUT;
	SDA_HIGH;
	_delay_us(10);
	SCL_HIGH;
	_delay_us(10);
	SCL_LOW;
}
unsigned char IIC_Wait_NACK(void)
{
	//等待应答信号。返回值:1接收应答失败。返回值:0接收应答成功
	unsigned char temptime=0;
	SDA_IN;
	SDA_HIGH;
	_delay_us(10);
	SCL_HIGH;
	_delay_us(10);
	while (SDA_READ)
	{
		temptime++;
		if(temptime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	SCL_LOW;
	return 0;
}
void IIC_Send_Byte(unsigned char data)
{
	unsigned char i=0;
	SDA_OUT;
	SCL_LOW;
	for (i=0;i<8;i++)
	{
		if ((data&0x80)>0)
			SDA_HIGH;
		else
			SDA_LOW;
			data<<=1;
			SCL_HIGH;
			_delay_us(10);
			SCL_LOW;
			_delay_us(10);
	}
	SCL_HIGH;
	_delay_us(10);
	SCL_LOW;
	_delay_us(10);
}
unsigned char IIC_Read_Byte(unsigned char ack)
{
	//读一个字节,ack=1时,发送ACK,ack=0时,发送NACK;
	unsigned char i=0,receive=0;
	SDA_IN;
	for (i=0;i<8;i++)
	{
		SCL_LOW;
		_delay_us(10);
		SCL_HIGH;
		_delay_us(10);
		receive<<=1;
		if (SDA_READ)
		{
			receive++;
		}
		_delay_us(10);
	}
	if (ack==0)
		IIC_NACK();
	else
		IIC_ACK();
	return receive;
}
void Waken(void)
{//起始信号+器件地址+等待时间(至少800us)+停止信号
	IIC_Start();
	IIC_Send_Byte(IIC_Address);
	SCL_LOW;
	_delay_us(800);
	IIC_Stop();	
}
void Clear_Data(void)
{
	int i;
	for (i=0;i<IIC_RX_Len;i++)
	{
		IIC_RX_Buffer[i]=0x00;//接收数据缓冲区清零
	}
}
unsigned int CRC16(unsigned char *ptr,unsigned char len)
{//生成CRC校验码,用于检测数据是否正确
	unsigned int crc=0xffff;
	unsigned char i;
	while (len--)
	{
		crc^=*ptr++;
		for (i=0;i<8;i++)
		{
			if (crc&0x1)
			{
				crc>>=1;
				crc^=0xa001;
			} 
			else
			{
				crc>>=1;
			}
		}
	}
	return crc;
}
unsigned char CheckCRC(unsigned char *ptr,unsigned char len)
{//检测CRC校验码,判断数据是否正确
	unsigned int crc;
	crc=(unsigned int)CRC16(ptr,len-2);
	if (ptr[len-1]==(crc>>8)&&ptr[len-2]==(crc&0x00ff))
	{
		return 0xff;
	} 
	else
	{
		return 0x0;
	}
}
unsigned char WriteNByte(unsigned char sla,unsigned char *s,unsigned char n)
{
	unsigned char i;
	IIC_Start();//IIC起始信号
	IIC_Send_Byte(sla);//发送器件地址
	for (i=0;i<n;i++)//发送读温湿度命令
	{
		IIC_Send_Byte(*(s+i));
	}
	IIC_Stop();//IIC停止信号
	return 1;
}
unsigned char ReadNByte(unsigned char sla,unsigned char *p,unsigned char n)
{
	unsigned char i;
	IIC_Start();//IIC起始信号
	IIC_Send_Byte(sla+0x01);//发送器件地址
	_delay_us(30);//延时不小于30us,才可以继续发送下一个串行时钟,进行读取数据
	for (i=0;i<n-1;i++)
	{
		*(p+i)=IIC_Read_Byte(1);//读取前n-1个字节数据,并发送应答信号
	}
	*(p+n-1)=IIC_Read_Byte(0);//读取最后一个字节数据,并发送非应答信号
	IIC_Stop();//IIC停止信号
	return 1;
}
void press_AM2322_Data(void)
{
	int Temp,Hum;
	int Temp1,Hum1;
	Clear_Data();//清空缓冲区
	WR_Flag=0;
	Waken();//唤醒传感器
	WriteNByte(IIC_Address,IIC_TX_Buffer,3);//发送读数据命令
	_delay_ms(2);//至少等待1.5ms发送读取时序、
	ReadNByte(IIC_Address,IIC_RX_Buffer,8);//读返回的温湿度数据
	_delay_ms(2);
	SDA_HIGH;
	SCL_HIGH;//释放总线
	if (WR_Flag == 0)
	{
		if (CheckCRC(IIC_RX_Buffer,8))
		{
			Hum1=IIC_RX_Buffer[2]*256+(IIC_RX_Buffer[3]>>4)*16+(((IIC_RX_Buffer[3]<<4)&0xf0)>>4);
			Hum=Hum1/10;
			Temp1=IIC_RX_Buffer[4]*256+(IIC_RX_Buffer[5]>>4)*16+(((IIC_RX_Buffer[5]<<4)&0xf0)>>4);
			Temp=Temp1/10;
			uart0_putchar(Hum, pRTbuf_UART0);
			uart0_putchar(Temp, pRTbuf_UART0);
		} 
		else
		{
			uart0_putchars(Error_Mess,5,pRTbuf_UART0);
		}
	} 
	else
	{
		uart0_putchars(Error_Mess,5,pRTbuf_UART0);
	}
	
}
回复

使用道具 举报

  离线 

8

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
147
金钱
147
注册时间
2017-3-8
在线时间
35 小时
 楼主| 发表于 2017-6-12 15:53:57 | 显示全部楼层
求帮助!谢谢
回复

使用道具 举报

  离线 

8

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
147
金钱
147
注册时间
2017-3-8
在线时间
35 小时
 楼主| 发表于 2017-6-12 16:38:56 | 显示全部楼层
温湿度检测模块的例程,求各位大神帮助!
回复

使用道具 举报

  离线 

8

主题

66

帖子

0

精华

初级会员

Rank: 2

积分
147
金钱
147
注册时间
2017-3-8
在线时间
35 小时
 楼主| 发表于 2017-6-12 18:12:26 | 显示全部楼层
自己顶,求助~
回复

使用道具 举报

  离线 

516

主题

9万

帖子

31

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
134732
金钱
134732
注册时间
2010-12-1
在线时间
1316 小时
发表于 2017-6-12 19:38:20 | 显示全部楼层
自己写吧
回复

使用道具 举报

  离线 

3

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2017-6-29
在线时间
9 小时
发表于 2018-3-1 13:59:02 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




关闭

正点原子双11大促销上一条 /1 下一条

正点原子公众号

QQ|联系我们|手机版|官方淘宝店|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-11-16 11:33

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */