打印

attiny9模拟I2C协议程序工作不正常

[复制链接]
811|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hstone11|  楼主 | 2017-2-24 20:57 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
烧写了attiny9程序,感觉总是不正常,好像根本没有跑起来,有高手指点一二吗?

#define F_CPU 4000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <avr/interrupt.h>


#define uchar unsigned char
#define uint unsigned int



        #define write_ADD 0x88
        #define read_ADD 0x89
       
        #define CONF_ADDR 0x01
        #define INTER_ADDR 0x02
        #define PROX_LT        0x03
        #define PROX_HT        0x04
        #define PROX_DATA 0x08
       
        #define CONF_PROXREG 0xA8//prox sensor is enable and the sleep time is 200ms(1010 1000)
        #define CONF_INTREG  0x00
       
       


#define I2C_SDA_OUT DDRB |= (1 << PORTB3)
#define I2C_SDA_IN  DDRB &= ~(1 << PORTB3)
#define I2C_SCL_OUT DDRB |= (1 << PORTB0)
#define I2C_SCL_IN  DDRB &= ~(1 << PORTB0)

#define SDA_WRT_H PORTB |= (1 << PORTB3)
#define SDA_WRT_L PORTB &= ~(1 << PORTB3)
#define SCL_WRT_H PORTB |= (1 << PORTB0)
#define SCL_WRT_L PORTB &= ~(1 << PORTB0)

#define ALERT_ON  PORTB |= (1 << PORTB2)
#define ALERT_OFF PORTB &= ~(1 << PORTB2)
//#define SDA_RED_H (PINB0 == 1)
#define SDA_READ        PINB3
void init_sys(void);
void I2c_init();                         //初始化

uchar I2c_respond();  //应答 SCL在高电平期间,SDA被从设备拉为低电平表示应答
void I2c_ACK(void);
void I2c_Start(void);
void I2c_Stop(void);
uchar I2c_write_byte(uchar dat);//写字节
void I2c_write(uchar addr,uchar dat);         //指定地址写
uchar I2c_read_byte(void);                        //读字节
uchar I2c_read(uchar addr);     //指定地址读
uchar g_bflag = 0;                //应答标志位
uchar g_ProxVal = 0;        //接近程度值
uchar g_proxH = 0xFF;        //接近度报警值

uint g_iTimebase = 0xFF;
void Conf_reg(void);
void SetProxVal(uchar prox_h, uchar prox_l);
void IsAlert(void);
//定时器初始化
void Timer_Init();
void Timer_changeMs(uchar ms100);//unit:100 ms
void SetSleepMode(uchar ms100);//unit:100ms
//定时器初始化
void Timer_Init()
{       
        TCCR0B = 0x05; //预分频1024
        g_iTimebase = F_CPU / 1024.0 * 0.1;//0.1s
        //Timer_changeMs(2);//0.2s中断
}
void Timer_changeMs(uchar ms100)
{
        //max is 16s
        if(ms100 > 160)
                ms100 = 160;
        uint uTimes = g_iTimebase * ms100;
        TCNT0L = 256 - (uTimes & 0xFF); //
        TCNT0H = 256 - ((uTimes >> 8) & 0xFF);
       
        TIMSK0 = 0x01; //使能T0中断
        //sei(); //开中断
}

ISR(TIM0_OVF_vect)
{
}
void SetSleepMode(uchar ms100)
{
         cli(); //disable all interrupts
         Timer_changeMs(ms100);
         sei(); //开中断
}
void init_sys(void)
{       
        //BBMB = 1;//break-before-make:pin input to output
        PORTCR = 0x01;
        I2C_SDA_OUT;
        I2C_SCL_OUT;       
}                  
//***************************************************************************
////开始信号
//在时钟线SCL为高电平时,数据线SDA由高向低跳变.
void I2c_Start()   
{     
        SDA_WRT_H;
        SCL_WRT_H;         
         
    _delay_us(5);
     
    //SDA = 0;
        SDA_WRT_L;  
    _delay_us(5);
       
        //SCL = 0;
        SCL_WRT_L;
        _delay_us(5);
}  
//***************************************************************************  
void I2c_Stop()   //停止 SCL在高电平期间,SDA一个上升沿则表示停止信号  
{  
     SDA_WRT_L;
     _delay_us(5);
                  
     SCL_WRT_H;
     _delay_us(5);
         
     SDA_WRT_H;  
}
//***************************************************************************  
uchar I2c_respond()  //应答 SCL在高电平期间,SDA被从设备拉为低电平表示应答  
{  
    uchar ACK = 0;
        SDA_WRT_H;
        SCL_WRT_H;       
       
        I2C_SDA_IN;
        _delay_us(5);
       
        ACK = ~SDA_READ;//?
        SCL_WRT_L;
        _delay_us(5);
        I2C_SDA_OUT;
        return ACK;   
}  
//***************************************************************************  
void I2c_init()//总线初始化 将总线都拉高一释放总线  发送启动信号前,要先初始化总线。即总有检测到总线空闲才开始发送启动信号  
{  
    //SDA = 1;  
        SDA_WRT_H;
    _delay_us(5);
         
    //SCL = 1;  
        SCL_WRT_H;
    _delay_us(5);
}  
//***************************************************************************  
uchar I2c_write_byte(uchar dat) //写一个字节  
{  
    uchar i;      
       
    for(i = 0; i < 8; i++)  
    {  
                if(((dat << i) & 0x80) > 0)
                {
                        SDA_WRT_H;
                }
                else
                {
                        SDA_WRT_L;
                }
                       
        //SCL = 1;
                SCL_WRT_L;
        _delay_us(5);
        //SCL = 0;
                SCL_WRT_L;
        _delay_us(5);
    }  
    //发送一个字节后,读取来自I2C芯片的响应.
    //即在发送完8个字节后,在第九个时钟内,SDA总线应为低电平,表示I2C芯片已经读取了数据.
    //否则为高电平.即发送败.  
        return I2c_respond();
}  
//***************************************************************************  
uchar I2c_read_byte(void)//读一个字节  
{  
    uchar i,k = 0;  
     
    //SDA = 1;
        SDA_WRT_H;   
        I2C_SDA_IN;
    for(i = 0; i < 8; i++)  
    {  
                SCL_WRT_H;
        //SCL = 1;//上升沿时,IIC设备将数据放在sda线上,并在高电平期间数据已经稳定,可以接收啦  
        _delay_us(5);
                     
        k = (k << 1) | SDA_READ;  
        //SCL = 0;//拉低SCL,使发送端可以把数据放在SDA上  
                SCL_WRT_L;
        _delay_us(5);
    }  
    return k;  
}  
//***************************************************************************  
void I2c_write(uchar addr, uchar dat)//任意地址写一个字节  
{  
    I2c_Start();//启动  
    I2c_write_byte(write_ADD);//发送从设备地址  
    I2c_respond();//等待从设备的响应  
    I2c_write_byte(addr);//发出芯片内地址  
    I2c_respond();//等待从设备的响应  
    I2c_write_byte(dat);//发送数据  
    I2c_respond();//等待从设备的响应  
    I2c_Stop();//停止  
}  
//***************************************************************************  
uchar I2c_read(uchar addr)//读取一个字节  
{  
    uchar dat;  
    I2c_Start();//启动  
    I2c_write_byte(write_ADD);//发送从设备地址 写操作  
    I2c_respond();//等待从设备的响应  
    I2c_write_byte(addr);//发送芯片内地址  
    I2c_respond();//等待从设备的响应  
    I2c_Start();//启动  
    I2c_write_byte(read_ADD);//发送从设备地址 读操作  
    I2c_respond();//等待从设备的响应  
    dat = I2c_read_byte();//获取数据  
    I2c_Stop();//停止  
    return dat;//返回数据  
}
void Conf_reg(void)
{
        uchar prox_l = 25;//FSR10%
        uchar prox_h = 50;//FSR20%
        uchar prox_max = 100;//FSR40%
        I2c_write(CONF_ADDR, CONF_PROXREG);//prox sensor enable and sleep mode 200ms
        I2c_write(INTER_ADDR, 0);
       
        prox_h = I2c_read(PROX_DATA);
       
        if(prox_h < prox_max && prox_h > prox_l)
        {
                prox_l = prox_h;               
        }
        g_ProxVal = prox_l << 1;
        I2c_write(PROX_LT, prox_l);
        I2c_write(PROX_HT, g_ProxVal);
}
int main(void)
{
        uchar prox_data = 0;
        //_delay_ms(1000);
        init_sys();
        I2c_init();
       
        Conf_reg();
    while(1)
    {
        //TODO:: Please write your application code
                prox_data = I2c_read(PROX_DATA);
                if(prox_data >= g_ProxVal)
                {
                        ALERT_ON;
                        //_delay_ms(5000);
                        SetSleepMode(50);//5s
                }
                //_delay_ms(205);
                ALERT_OFF;
                SetSleepMode(2);//0.2s               
    }
}

相关帖子

沙发
hstone11|  楼主 | 2017-3-1 17:37 | 显示全部楼层
写了个最简单的程序下载后都没有反应,是不是下载时候设置不对吗?使用Atmel studio6.2编译并下载,器件选择attiny9(TPI),symbols中设置 F_CPU=4000000UL.烧录显示OK,上电后就是没有输出。
#define F_CPU 4000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int main(void)
{
        DDRB = 0xFF;
       
        PORTB = 0;
        _delay_ms(1000);
    while(1)
    {
        //TODO:: Please write your application code
                PORTB = 0xFF;
                _delay_ms(5000);
                PORTB = 0;
                _delay_ms(5000);
    }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

3

帖子

0

粉丝