snow_person01 发表于 2008-5-6 21:34:54

请马老师帮忙看看我用m16与qt6024使用i2c通信的程序是哪儿错了,谢谢

我在用cvavr编译器编写 m16与qt6024通信时使用m16的twi能成功,而使用系统自带的库函数不行,不知道是为什么?
使用qt6024实现3*4键盘

使用TWI功能程序如下,能成功返回值.
#defineQT60240_IIC_ADDRESS0xe   //0x0e//0x22//0xea
#defineFAIL               1
#defineSUCCESS            0

#include <mega16.h>
        #ifndef __SLEEP_DEFINED__
        #define __SLEEP_DEFINED__
        .EQU __se_bit=0x40
        .EQU __sm_mask=0xB0
        .EQU __sm_powerdown=0x20
        .EQU __sm_powersave=0x30
        .EQU __sm_standby=0xA0
        .EQU __sm_ext_standby=0xB0
        .EQU __sm_adc_noise_red=0x10
        .SET power_ctrl_reg=mcucr
        #endif
#include <delay.h>

#defineSTART                0x08
#defineMT_SLA_ACK         0x18
#defineREPEATED_START       0x10
#defineMT_DATA_ACK          0x28

#include <stdio.h>

#define TWPS0                   0
#define TWPS1                   1
#define TWGCE                   0
#define TWINT                   7
#define TWEA                  6
#define TWSTA                   5
#define TWSTO                   4
#define TWWC                  3
#define TWEN                  2
#define TWIE                  0
unsigned char receive_data;
void IIC_Init(void)
{
TWSR=0;
TWBR=0X20;
TWAR=0;
TWCR=0X44;
PORTC.0=1;
DDRC=0xff;
PORTC.1=1;

}


unsigned char Writing_IIC_Data(unsigned char mem_addr,unsigned char idata)
{

        //发出START 信号
        TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

        //等待TWINT 置位, TWINT 置位表示START 信号已发出
        while (!(TWCR & (1<<TWINT)));

        //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是START 转出错处理
        if ((TWSR & 0xF8) != START)
             return FAIL;

        //装入SLA_W 到TWDR 寄存器,TWINT 位清零,启动发送地址
        TWDR = QT60240_IIC_ADDRESS;
      TWCR = (1<<TWINT) | (1<<TWEN);

      //等待TWINT 置位, TWINT 置位表示总线命令SLA+W 已发出,及收到应答信号ACK/NACK
      while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MT_SLA_ACK 转出错处理
      if ((TWSR & 0xF8) != MT_SLA_ACK)
             return FAIL;

      //装入数据到TWDR 寄存器,TWINT 清零,启动发送数据
      TWDR = mem_addr;
      TWCR = (1<<TWINT) | (1<<TWEN);

      //等待 TWINT 置位, TWINT 置位表示总线数据 DATA 已发送,及收到应答信号 ACK/NACK
      while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频器,如果状态字不是MT_DATA_ACK 转出错处理
      if ((TWSR & 0xF8) != MT_DATA_ACK)
             return FAIL;

      //装入数据到TWDR 寄存器,TWINT 清零,启动发送数据
      TWDR = idata;
      TWCR = (1<<TWINT) | (1<<TWEN);

      //等待 TWINT 置位, TWINT 置位表示总线数据 DATA 已发送,及收到应答信号 ACK/NACK
      while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频器,如果状态字不是MT_DATA_ACK 转出错处理
      if ((TWSR & 0xF8) != MT_DATA_ACK)
             return FAIL;

      //发送STOP 信号
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);

      return SUCCESS;
}


unsigned char Reading_IIC_Data(unsigned char mem_addr)
{

        //发出START 信号
        TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

        //等待TWINT 置位, TWINT 置位表示START 信号已发出
        while (!(TWCR & (1<<TWINT)));

        //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是START 转出错处理
        if ((TWSR & 0xF8) != START)
           return FAIL;

        //装入SLA_W 到TWDR 寄存器,TWINT 位清零,启动发送地址
        TWDR = QT60240_IIC_ADDRESS;
      TWCR = (1<<TWINT) | (1<<TWEN);

      //等待TWINT 置位, TWINT 置位表示总线命令SLA+W 已发出,及收到应答信号ACK/NACK
      while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MT_SLA_ACK 转出错处理
      if ((TWSR & 0xF8) != MT_SLA_ACK)
             return FAIL;

      //装入数据到TWDR 寄存器,TWINT 清零,启动发送数据
      TWDR = mem_addr;
      TWCR = (1<<TWINT) | (1<<TWEN);

      //等待 TWINT 置位, TWINT 置位表示总线数据 DATA 已发送,及收到应答信号 ACK/NACK
      while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频器,如果状态字不是MT_DATA_ACK 转出错处理
      if ((TWSR & 0xF8) != MT_DATA_ACK)
             return FAIL;

        //重复发出START 信号
        TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

        //等待TWINT 置位, TWINT 置位表示START 信号已发出
        while (!(TWCR & (1<<TWINT)));

        //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是START 转出错处理
        if ((TWSR & 0xF8) != REPEATED_START)
             return FAIL;

        //装入SLA_R 到TWDR 寄存器,TWINT 位清零,启动发送地址
        TWDR = QT60240_IIC_ADDRESS+1;
      TWCR = (1<<TWINT) | (1<<TWEN);

      //等待TWINT 置位, TWINT 置位表示总线命令SLA+R 已发出,及收到应答信号ACK/NACK
      while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MT_SLA_ACK 转出错处理
      if ((TWSR & 0xF8) != 0x40)
             return FAIL;

      TWCR = (1<<TWINT) | (1<<TWEN);

        //等待TWINT 置位, TWINT 置位表示数据已接收
        while (!(TWCR & (1<<TWINT)));

      //检验TWI 状态寄存器,屏蔽预分频位,如果状态字不是MT_SLA_ACK 转出错处理
      if ((TWSR & 0xF8) != 0x58)
             return FAIL;

      //接收的数据
      receive_data = TWDR;

      //发送STOP 信号
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);

      return SUCCESS;

}

void clear_iic(void)
{
      //发送STOP 信号
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}


void main(void)
{
unsigned char i,key;
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T


// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x80;
DDRD=0x80;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
putchar(0x11);

// I2C Bus initialization
IIC_Init();
while (1)
      {
       for(i=1;i<4;i++)
       {
       Reading_IIC_Data(i);
       if(receive_data!=0)
       {
       switch (receive_data)
       {
       case 1:if(i==1) {key=3; break;}
            if(i==2) {key=2;break;}
            if(i==3) {key=1;break;}
       case 2:if(i==1) {key=6; break;}
            if(i==2) {key=5;break;}
            if(i==3) {key=4;break;}
       case 4:if(i==1) {key=9; break;}
            if(i==2) {key=8;break;}
            if(i==3) {key=7;break;}
       case 8:if(i==1) {key='#'; break;}
            if(i==2) {key=0;break;}
            if(i==3) {key='*';break;}

       }
      putchar(key);

      }
       delay_ms(150);
       }
      };
}





使用自带的库函数程序如下,此时使用的是 PA口,只读地址1里面的数据

/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.9 Professional
Automatic Program Generator
?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 2008/5/6
Author: SNOW
Company : SEELO
Comments:


Chip type         : ATmega16L
Program type      : Application
Clock frequency   : 7.372800 MHz
Memory model      : Small
External SRAM size: 0
Data Stack size   : 256
*****************************************************/

#include <mega16.h>
        #ifndef __SLEEP_DEFINED__
        #define __SLEEP_DEFINED__
        .EQU __se_bit=0x40
        .EQU __sm_mask=0xB0
        .EQU __sm_powerdown=0x20
        .EQU __sm_powersave=0x30
        .EQU __sm_standby=0xA0
        .EQU __sm_ext_standby=0xB0
        .EQU __sm_adc_noise_red=0x10
        .SET power_ctrl_reg=mcucr
        #endif

// I2C Bus functions
#asm
   .equ __i2c_port=0x1B ;PORTA
   .equ __sda_bit=0
   .equ __scl_bit=1
#endasm
#include <i2c.h>
#include <delay.h>
#include <stdio.h>
#define add    0x0e

unsigned char rd_qt6024(unsigned char meu_add)
{
unsigned char data;
i2c_start();
i2c_write(add);
i2c_write(meu_add);
i2c_start();
i2c_write(add|1);
data=i2c_read(1);
i2c_stop();
return data;
}
void main(void)
{
unsigned char data;
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F;
i2c_init();
while (1)
      {
   data=rd_qt6024(1);
   putchar(data);
   delay_ms(1000);

      };
}

不管有没有键触摸到,返回值为0Xff和oxDF交替出现.有时还可能是其它的值,都非正确值,不知是为什么。

附带传上qt6024的datasheet

请马老师和知道原因的朋友帮忙看看,不慎感谢。


点击此处下载 ourdev_268182.pdf(文件大小:344K) (原文件名:QT60240_X002.pdf)

snow_person01 发表于 2008-5-6 21:37:19

还有一个问题,在使用cvavr自带的i2c库时,其传输速度是多少?

machao 发表于 2008-5-9 18:37:33

程序就不看了,你愿意的话,买本我的教材学习I2C的使用,里面有不同方式的例程.

cvavr自带的i2c库,其CLK好象是标准的400KHZ.

snow_person01 发表于 2008-5-13 14:02:28

谢谢马老师的回复,书正在看,还没能实现用软件实现。我再好好的看看我的程序。

gwh1128 发表于 2008-6-5 16:35:11

可能是速度太快了阿,那个芯片最快100K的阿

yanzaihong 发表于 2011-7-30 22:53:55

请问下3楼,马老师的书那在卖!得赶紧买来学习!望推荐下!

tianyaxtujxlg 发表于 2011-9-23 11:33:44

回复【2楼】machao
-----------------------------------------------------------------------

马老师有没有430F249的硬I2C的从机接受程序,或者初始化的程序也好。我现在用它做I2C的从机,但是总是无法给主机应答信号。主机发送过来的地址和数据我用示波器看过了,都是正常的,但是从机430F249就是没有反应,给不出应答信号,我采用查询的方式,就是发现从机的 开始标志位UCSTTIFG 没有被置位。请问马老师这个问题出在哪里啊?我这边很急,在此先谢谢马老师了
页: [1]
查看完整版本: 请马老师帮忙看看我用m16与qt6024使用i2c通信的程序是哪儿错了,谢谢