OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2574|回复: 6

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

[复制链接]

8

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
421
金钱
421
注册时间
2017-3-8
在线时间
114 小时
发表于 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
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
421
金钱
421
注册时间
2017-3-8
在线时间
114 小时
 楼主| 发表于 2017-6-12 15:53:45 | 显示全部楼层
自己写的,还没测试,希望你们也能用得上。[mw_shl_code=c,true]//模拟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=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);
        }
       
}[/mw_shl_code]
回复

使用道具 举报

8

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

8

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

8

主题

182

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

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

使用道具 举报

3

主题

25

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 20:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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