搜索
bottom↓
回复: 6

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

[复制链接]

出0入0汤圆

发表于 2008-5-6 21:34:54 | 显示全部楼层 |阅读模式
我在用cvavr编译器编写 m16与qt6024通信时使用m16的twi能成功,而使用系统自带的库函数不行,不知道是为什么?
使用qt6024实现3*4键盘

使用TWI功能程序如下,能成功返回值.
#define  QT60240_IIC_ADDRESS  0xe   //0x0e  //0x22  //0xea
#define  FAIL                 1
#define  SUCCESS              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>

#define  START                0x08
#define  MT_SLA_ACK           0x18
#define  REPEATED_START       0x10
#define  MT_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)

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2008-5-6 21:37:19 | 显示全部楼层
还有一个问题,在使用cvavr自带的i2c库时,其传输速度是多少?

出0入0汤圆

发表于 2008-5-9 18:37:33 | 显示全部楼层
程序就不看了,你愿意的话,买本我的教材学习I2C的使用,里面有不同方式的例程.

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

出0入0汤圆

 楼主| 发表于 2008-5-13 14:02:28 | 显示全部楼层
谢谢马老师的回复,书正在看,还没能实现用软件实现。我再好好的看看我的程序。

出0入0汤圆

发表于 2008-6-5 16:35:11 | 显示全部楼层
可能是速度太快了阿,那个芯片最快100K的阿

出0入0汤圆

发表于 2011-7-30 22:53:55 | 显示全部楼层
请问下3楼,马老师的书那在卖!得赶紧买来学习!望推荐下!

出0入0汤圆

发表于 2011-9-23 11:33:44 | 显示全部楼层
回复【2楼】machao
-----------------------------------------------------------------------

马老师有没有430F249的硬I2C的从机接受程序,或者初始化的程序也好。我现在用它做I2C的从机,但是总是无法给主机应答信号。主机发送过来的地址和数据我用示波器看过了,都是正常的,但是从机430F249就是没有反应,给不出应答信号,我采用查询的方式,就是发现从机的 开始标志位UCSTTIFG 没有被置位。请问马老师这个问题出在哪里啊?  我这边很急,在此先谢谢马老师了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 19:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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