ATmega16的TWI(I2C)读取MMA7455角加速度仪死活调不出来,求助
我用ATmega16的TWI模块读取角加速度仪传感器MMA7455的数据,总是在开始信号发送等待应答位的时候工作就不正常了,不知道是什么原因。原来用51单片机模拟I2C一点问题也没有,但是在AVR上用TWI模块就是不行(已经设置上拉电阻),求哪位大神帮我看下我的程序
这是I2C的头文件I2C.h
#ifndef _PMU_TEMPERATURE_H
#define _PMU_TEMPERATURE_H
//I2C 状态定义
//MT 主方式传输 MR 主方式接受
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
//常用TWI操作(主模式写和读)
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) //作为主机启动I2C
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) //停止I2C
#define Wait() {while(!(TWCR&(1<<TWINT)));} //等待中断发生
#define TestAck() (TWSR&0xf8) //观察返回状态
#define SetAck() (TWCR|=(1<<TWEA)) //做出ACK应答
#define SetNoAck() (TWCR&=~(1<<TWEA)) //做出Not ACK应答
#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN)) //启动I2C
#define WriteByte(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} //写数据到TWDR
#define TWI_ACT ((1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA))
unsigned char f_I2cWrite(unsigned char Wdata,unsigned char RegAddress); //I2C写
signed int f_I2cRead(unsigned char RegAddress);
#endif
这是I2C.c文件
#include <avr/io.h>
#include "I2C.h"
#define uchar unsigned char
#define uint unsigned int
#define WD_DEVICE_ADDR 0x1D
#define RD_DEVICE_ADDR 0x1D
uchar Delay_ms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<800;j++);
}
uchar f_I2cWrite(uchar Wdata,uchar RegAddress) //I2C总线写一字节返回1:写成功返回0:写失败
{
Start(); //I2C启动
Wait();
if(TestAck()!=START) return 12; //ACK
//uint t=WD_DEVICE_ADDR<<1;
WriteByte(WD_DEVICE_ADDR); //写入I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK) return 2; //ACK
WriteByte(RegAddress); //写相应寄存器地址
Wait();
if(TestAck()!=MT_DATA_ACK) return 3;
WriteByte(Wdata); //写数据
Wait();
if(TestAck()!=MT_SLA_ACK) return 4; //ACK
Stop(); //I2C停止
Delay_ms(10);
return 0;
}
signed int f_I2cRead(uchar RegAddress) //I2C总线读一个字节 返回0:失败 返回非0:成功
{
signed int siTemp;
Start(); //I2C启动
Wait();
if(TestAck()!=START) return 1; //ACK
uint t=WD_DEVICE_ADDR;
WriteByte(WD_DEVICE_ADDR); //写入I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK) return 2; //ACK
WriteByte(RegAddress+1); //写ROM地址
Wait();
if(TestAck()!=MT_DATA_ACK) return 3;
Start(); //I2C重新启动
Wait();
if(TestAck()!=RE_START) return 4;
t=(RD_DEVICE_ADDR)+1;
WriteByte(RD_DEVICE_ADDR); //写I2C从器件地址和读方式
Wait();
if(TestAck()!=MR_SLA_ACK) return 5; //ACK
if(RegAddress==0x00)
{
Twi(); //启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK) return 0; //ACK
siTemp=TWDR; //读取I2C接收数据
siTemp=siTemp<<8;
Twi(); //再次启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK) return 0; //ACK
siTemp+=TWDR; //读取I2C接收数据
SetAck();
Stop(); //I2C停止
siTemp=siTemp>>6;
siTemp=siTemp/4;
}
else
{
Twi(); //启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK) return 0; //ACK
siTemp=TWDR; //读取I2C接收数据
//siTemp=siTemp/4;
SetAck();
Stop(); //I2C停止
}
return siTemp; //返回值
}
这是主函数
int main()
{
InitPort(); //DDRC=0x02;PORTC=0x03;
InitI2C();
float n;
f_I2cWrite(0x16,0x05);
TurnOff();
while(1)
{
n=f_I2cRead(0x07);
Display(n);
}
}
程序结果:显示的值一直都是1(在f_I2cRead()函数中设置第一个应答位如果没有接受到return 1;) {:lol:} 估计你只是设置了IO口的内部上拉电阻吧?用AVR的TWI一定要外接上拉电阻!!我以前曾在这上面浪费了一个星期时间呐~~ BBC 发表于 2012-6-17 02:44 static/image/common/back.gif
估计你只是设置了IO口的内部上拉电阻吧?用AVR的TWI一定要外接上拉电阻!!我以前曾在这上面浪费了 ...
可是我后来是接了外部上拉电阻的啊……而且当时我用51调的时候没有设置上拉电阻照样可以用。AVR的时候不管是模拟还是模块I2C都没用。
你那儿有这个芯片能用的程序么?能让我借鉴一下么?谢了哦!!! wlkobe 发表于 2012-6-17 22:09 static/image/common/back.gif
可是我后来是接了外部上拉电阻的啊……而且当时我用51调的时候没有设置上拉电阻照样可以用。AVR的时候不 ...
//Atmega8 @ 8MHz
//ICCAVR v7
#include "iom8v.h"
#include <macros.h>
#define Start() ( TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) ) //产生START信号
#define Stop()( TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN) ) //产生STOP信号
#define tea5767_add_w 0xC0
#define tea5767_add_r 0xC1
unsigned int freq = 10800;
unsigned char rx;
unsigned int cal_pll( unsigned long temp )
{
unsigned int ans;
ans = (unsigned int)(((temp*10-225)*4000)/32768);
return ans;
}
void TWI_write( unsigned char twi_d )
{
TWDR = ( twi_d );
TWCR = ( 1<<TWINT ) | ( 1<<TWEN );
}
void TWI_init( void )
{
TWCR=0X00; //关闭TWI总线
TWBR=0x12; //设置传输比特率
TWSR=0x03; //设置TWI总线的速度,频率不能大于400K,否则5767不工作
TWCR=0x04; //使能TWI总线
}
unsigned char TWI_read( void )
{
unsigned char temp;
TWCR |= 0x04;
while(!(TWCR&(1<<TWINT)));
temp = TWDR;
return temp;
}
void read_5767( void )
{
unsigned char k;
Start();
while(!(TWCR&(1<<TWINT)));
TWI_write(tea5767_add_r);
while(!(TWCR&(1<<TWINT)));
for(k=0;k<5;k++)
{
rx = TWI_read();
}
}
void write_5767( unsigned char tx0, unsigned char tx1, unsigned char tx2, unsigned char tx3, unsigned char tx4 )
{
Start();
while(!(TWCR&(1<<TWINT)));
TWI_write( tea5767_add_w );
while(!(TWCR&(1<<TWINT)));
TWI_write(tx0);
while(!(TWCR&(1<<TWINT)));
TWI_write(tx1);
while(!(TWCR&(1<<TWINT)));
TWI_write(tx2);
while(!(TWCR&(1<<TWINT)));
TWI_write(tx3);
while(!(TWCR&(1<<TWINT)));
TWI_write(tx4);
while(!(TWCR&(1<<TWINT)));
Stop();
}
void init_5767( void )
{
unsigned int pll;
pll = cal_pll( freq );
write_5767( pll/256|0x80, pll%256, 0x09, 0x90, 0x01 ); //mute
//write_5767( pll/256&(~0x80), pll%256, 0x09, 0x90, 0x01 );//unmute
}{:lol:} 这里有个TEA5767的IIC,希望有用...... BBC 发表于 2012-6-18 12:42 static/image/common/back.gif
这里有个TEA5767的IIC,希望有用......
后天考试,考完试好好研究研究,谢啦哈!!!{:biggrin:} BBC 发表于 2012-6-18 12:42 static/image/common/back.gif
这里有个TEA5767的IIC,希望有用......
你好,我还想问下你读取数据的时候调用了中断么? lz 给你个提示,利用icc 产生一个 twi程序在试试,一般都是可以的
wlkobe 发表于 2012-6-18 22:24 static/image/common/back.gif
你好,我还想问下你读取数据的时候调用了中断么?
{:lol:} 没有用中断...不过在等待的时候不断查询中断标志:while(!(TWCR&(1<<TWINT))); BBC 发表于 2012-6-19 00:21 static/image/common/back.gif
没有用中断...不过在等待的时候不断查询中断标志:while(!(TWCR&(1
哎?我用了下你的程序,发现我程序里像这种if(TestAck()!=START)判断应答位的语句只要有了,就有问题,无语哎……
现在写数据没什么问题了,可是读数据的时候貌似还是不行额……你平时用的时候功能一切正常的么? rei1984 发表于 2012-6-18 22:27 static/image/common/back.gif
lz 给你个提示,利用icc 产生一个 twi程序在试试,一般都是可以的
这个可以自动生成的么? 本帖最后由 BBC 于 2012-6-21 22:33 编辑
wlkobe 发表于 2012-6-21 21:55 static/image/common/back.gif
哎?我用了下你的程序,发现我程序里像这种if(TestAck()!=START)判断应答位的语句只要有了,就有问题,无 ...
我估计是IIC操作顺序问题......
哈哈,不好意思,刚才看你程序的注释,搞错了......操作顺序如下:
1. 发送start指令
2. 查询start命令是否发送成功(非必要)
3. 写从机地址
4. 等待从机ACK
......
{:lol:} 希望有用......
附上截图:
上图图例:
BBC 发表于 2012-6-21 22:27 static/image/common/back.gif
我估计是IIC操作顺序问题......
哈哈,不好意思,刚才看你程序的注释,搞错了......操作顺序如下:
其实我的等待Wait()是{while(!(TWCR&(1<<TWINT)));}和你的程序是一样的额……
啊哦,我们要关门了,明天再调,谢了哈!明天再讨论{:biggrin:} wlkobe 发表于 2012-6-21 22:49 static/image/common/back.gif
其实我的等待Wait()是{while(!(TWCR&(1
{:lol:} 哈哈,是啊,但是你后一句的注释是ACK,刚刚被这个给骗了,还以为你的操作顺序有问题......
wait()是等待IIC操作完成,if(TestAck()!=START)是查询start命令是否发出......这些都是芯片内部的查询操作啊,怎么会卡住呢...... BBC 发表于 2012-6-21 22:56 static/image/common/back.gif
哈哈,是啊,但是你后一句的注释是ACK,刚刚被这个给骗了,还以为你的操作顺序有问题......
wait ...
所以很奇怪啊,我后来发IF语句全都去了,然后在示波器里看波形,start,ack,stop这些都没有问题 BBC 发表于 2012-6-21 22:56 static/image/common/back.gif
哈哈,是啊,但是你后一句的注释是ACK,刚刚被这个给骗了,还以为你的操作顺序有问题......
wait ...
你好,我想问下TWI是TWINT为1时工作还是为0时工作啊,我看的有点糊涂了…… BBC 发表于 2012-6-21 22:56 static/image/common/back.gif
哈哈,是啊,但是你后一句的注释是ACK,刚刚被这个给骗了,还以为你的操作顺序有问题......
wait ...
你好,我想问下你当时IO口是怎么设置的啊? wlkobe 发表于 2012-6-22 17:19 static/image/common/back.gif
你好,我想问下你当时IO口是怎么设置的啊?
当TWINT为0的时候,表示IIC正在工作。
当IIC完成当前工作后(或者收到数据等等),TWINT变为1(置位)。
其实怪就怪在下面这里 :
在TWINT变为1(置位)之后,程序处理完当前数据,并且需要IIC做下一步工作的时候,要对TWINT位写“1”来对其清零......{:titter:}
IO设置的话,我的SCL设为输出,SDA设为输入。 怪就怪在这啊,如果TWINT在工作完成后置为while(!(TWCR&(1<<TWINT)));的结果不久成了继续循环了么,这样的话和程序的本意不是相反了么?
话说我的TWI快调出来了,嘿嘿,不过还是接收不到数据…… BBC 发表于 2012-6-22 18:07 static/image/common/back.gif
当TWINT为0的时候,表示IIC正在工作。
当IIC完成当前工作后(或者收到数据等等),TWINT变为1(置位)。 ...
怪就怪在这啊,如果TWINT在工作完成后置为while(!(TWCR&(1<<TWINT)));的结果不久成了继续循环了么,这样的话和程序的本意不是相反了么?
话说我的TWI快调出来了,嘿嘿,不过还是接收不到数据……… wlkobe 发表于 2012-6-22 18:47 static/image/common/back.gif
怪就怪在这啊,如果TWINT在工作完成后置为while(!(TWCR&(1
{:lol:}也不是啊,如果IIC工作完成了,TWINT就为1,直到下一次对IIC的操作。
所以,如果IIC工作未完成,( TWCR&(1<<TWINT) ) 就为0,!(TWCR&(1<<TWINT)) 为真,while(!(TWCR&(1<<TWINT))) ; 会一直循环直到IIC工作完成后。
如果工作完成了,( TWCR&(1<<TWINT) )为1,!(TWCR&(1<<TWINT)) 为假,while(!(TWCR&(1<<TWINT))) ; 这句判断一下之后直接跳过,不会循环啵... 前段时间调过ATmega16的IIC,中断方式,具体内容已经忘了,悲剧,不过挺好用的!! xlwq 发表于 2012-6-22 20:44 static/image/common/back.gif
前段时间调过ATmega16的IIC,中断方式,具体内容已经忘了,悲剧,不过挺好用的!! ...
想问一下中断内部写的大概是什么方面的程序呢? wlkobe 发表于 2012-6-22 20:47 static/image/common/back.gif
想问一下中断内部写的大概是什么方面的程序呢?
每个应答信号后,对应的状态是不一样的,并会触发一次中断,可以读取当前状态寄存器来确定,中断里面用状态机的方式来进行状态判断,然后处理数据! xlwq 发表于 2012-6-22 20:58 static/image/common/back.gif
每个应答信号后,对应的状态是不一样的,并会触发一次中断,可以读取当前状态寄存器来确定,中断里面用状 ...
哦,我貌似今天下午见过类似的程序,试试看,谢了哈! wlkobe 发表于 2012-6-22 22:23 static/image/common/back.gif
哦,我貌似今天下午见过类似的程序,试试看,谢了哈!
嗯!!这个方式还是很稳定的!比较好用。 xlwq 发表于 2012-6-22 22:47 static/image/common/back.gif
嗯!!这个方式还是很稳定的!比较好用。
你好,我这里有个问题想让你帮我看一下
我是用的是AVR Stdio 5 ,在使用定时中断时总是出现这个错误:ignoring #pragma interrupt_handler PWM
不知道到底是什么原因呢?应该如何解决,谢谢 AVR studio5 用的是GCC编译器!你的中断函数是
SIGNAL(SIG_INTERRUPT0) //外部中断0
{
}
这种格式吗? 我用了那种格式可是错误更多了
警告 1 statement with no effect E:\AVR\Programs\ROBOTS\ROBOTS\ROBOTS\ROBOTS.c 11 2 ROBOTS
警告 2 large integer implicitly truncated to unsigned type E:\AVR\Programs\ROBOTS\ROBOTS\ROBOTS\ROBOTS.c 26 2 ROBOTS
错误 3 expected identifier or '(' before numeric constant E:\AVR\Programs\ROBOTS\ROBOTS\ROBOTS\ROBOTS.c 32 1 ROBOTS
错误 4 expected identifier or '(' before numeric constant E:\AVR\Programs\ROBOTS\ROBOTS\ROBOTS\ROBOTS.c 32 1 ROBOTS
BBC 发表于 2012-6-22 18:07 static/image/common/back.gif
当TWINT为0的时候,表示IIC正在工作。
当IIC完成当前工作后(或者收到数据等等),TWINT变为1(置位)。 ...
你好,我这里有个问题想让你帮我看一下
我是用的是AVR Stdio 5 ,在使用定时中断时总是出现这个错误:ignoring #pragma interrupt_handler PWM
不知道到底是什么原因呢?应该如何解决,谢谢 wlkobe 发表于 2012-7-15 21:51 static/image/common/back.gif
你好,我这里有个问题想让你帮我看一下
我是用的是AVR Stdio 5 ,在使用定时中断时总是出现这个错误:ign ...
{:lol:} 请把代码贴出来吧...估计是程序里的中断向量名和头文件里宏定义的有出入 BBC 发表于 2012-7-19 20:43 static/image/common/back.gif
请把代码贴出来吧...估计是程序里的中断向量名和头文件里宏定义的有出入 ...
问题已经解决了,嘿嘿。是因为Studio是GCC的,而program这种语句是ICC才有的,所以自然就编译不了了
对了,你原来用AVR的定时中断模拟过PWM么?模拟出来的频率跟预设的误差有多少啊?我的误差貌似特别大的说不知道是原本就这样还是其他原因
这是我的程序:
void InitTimer()
{
CLI();
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=0xFF;
TCNT1L=0xFF;
TIMSK|=(1<<TOIE1);
SEI();
}
SIGNAL(TIMER1_OVF_vect)
{
TCNT1H=0xFF;
TCNT1L=0xFF;
PORTA=~PORTA;
}
所用的是8M的晶振,但是出来的频率是108KHz…… wlkobe 发表于 2012-7-20 17:08 static/image/common/back.gif
问题已经解决了,嘿嘿。是因为Studio是GCC的,而program这种语句是ICC才有的,所以自然就编译不了了
对 ...
呵呵,这个问题我也遇到过,原因是IO口也有它自己的工作时钟,所以这样模拟的频率并不一定就是定时器的频率~ 谁有计算8451角度的公式啊 这是我写的I2C通信的头文件,你可以先检查下I2C是不是有问题。我用它调过ADXL345,所以这个头文件保证没错。#ifndef __I2C_h
#define __I2C_h
#include"Delay.h"
#define uint unsigned int
#define uchar unsigned char
#define Baud_set 25 //TWI波特率设置
#define P_value 0X00//预分频值
//TWI读写操作公共步骤
#define ST_FAIL 0 //出错状态
#define ST_START 1 //START状态检查
#define ST_SLAW 2 //SLAW状态检查
#define ST_WADDR 3 //ADDR状态检查
//TWI读操作步骤
#define ST_RESTART 4 //RESTART状态检查
#define ST_SLAR 5 //SLAR状态检查
#define ST_RDATA 6 //读取数据状态检查,循环n字节
//TWI写操作步骤
#define ST_WDATA 7 //写数据状态检查,循环n字节
#define FAIL_MAX 20 //重试次数最大值
/**********************I2C状态定义*************************/
/************************主机发送状态码********************/
#define TW_START 0x08 //START已发送
#define TW_REP_START 0x10 //重复START已发送
#define TW_MT_SLA_ACK 0x18 //SLA+W 已发送收到ACK
#define TW_MT_SLA_NACK 0x20 //SLA+W 已发送接收到NOT ACK
#define TW_MT_DATA_ACK 0x28 //数据已发送接收到ACK
#define TW_MT_DATA_NACK 0x30 //数据已发送接收到NOT ACK
#define TW_MT_ARB_LOST 0x38 //SLA+W 或数据的仲裁失败
/*************************主机接收状态码*****************/
#define TW_START 0x08 //START已发送
#define TW_REP_START 0x10 //重复START已发送
#define TW_MR_ARB_LOST 0x38 //SLA+R 或NOT ACK 的仲裁失败
#define TW_MR_SLA_ACK 0x40 //SLA+R 已发送接收到ACK
#define TW_MR_SLA_NACK 0x48 //SLA+R 已发送接收到NOT ACK
#define TW_MR_DATA_ACK 0x50 //接收到数据ACK 已返回
#define TW_MR_DATA_NACK 0x58 //接收到数据NOT ACK已返回
/************************常用TWI操作***************************/
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) //启动I2C
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) //停止I2C
#define Wait() {while(!(TWCR&(1<<TWINT)));} //等待中断发生
#define TestAck() (TWSR&0xf8) //观察返回状态
#define SetAck (TWCR|=(1<<TWEA)) //做出ACK应答
#define SetNoAck (TWCR&=~(1<<TWEA)) //做出Not Ack应答
#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN)) //启动I2C
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} //写数据到TWDR
/************************从机接收状态码******************
#define TW_SR_SLA_ACK 0x60 //自己的SLA+W 已经被接收ACK已返回
#define TW_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收ACK 已返回
#define TW_SR_GCALL_ACK 0x70 //接收到广播地址ACK 已返回
#define TW_SR_ARB_LOST_GCALL_ACK 0x78 //SLA+R/W 作为主机的仲裁失败;接收到广播地址ACK已返回
#define TW_SR_DATA_ACK 0x80 //以前以自己的SLA+W被寻址;数据已经被接收ACK已返回
#define TW_SR_DATA_NACK 0x88 //以前以自己的SLA+W被寻址;数据已经被接收NOT ACK已返回
#define TW_SR_GCALL_DATA_ACK 0x90 //以前以广播方式被寻址;数据已经被接收ACK已返回
#define TW_SR_GCALL_DATA_NACK 0x98 //以前以广播方式被寻址;数据已经被接收NOT ACK已返回
#define TW_SR_STOP 0xA0 //在以从机工作时接收到STOP或重复START
/*************************从发送状态码*******************
#define TW_ST_SLA_ACK 0xA8 //自己的SLA+R 已经被接收ACK 已返回
#define TW_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收ACK 已返回
#define TW_ST_DATA_ACK 0xB8 //TWDR 里数据已经发送接收到ACK
#define TW_ST_DATA_NACK 0xC0 //TWDR 里数据已经发送接收到NOT ACK
#define TW_ST_LAST_DATA 0xC8 //TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK
/****************************其它状态码*****************
#define TW_NO_INFO 0xF8 //没有相关的状态信息;TWINT = “0”
#define TW_BUS_ERROR 0x00 //由于非法的START 或STOP 引起的总线错误
/******************************************************/
/****************************************************
函数名:TWI_init
作用:TWI接口的初始化
*****************************************************/
void TWI_init(void)
{
TWCR = 0x00; //关闭TWI模块
TWAR = 0x00; //主机模式,该地址无效
TWBR = Baud_set; //25
TWSR = P_value; //1分频
TWCR= 0x04; //使能TWI,禁止中断
}
/****************************************************/
//函数名:I2C_write
//作用:I2C通信中的写操作
uchar I2C_write(uchar SLA_WR_address,uchar wr_address,uchar wr_data)
{
Start(); //发送开始信号
Wait(); //0x08,等待信号发出
if(TestAck()!=TW_START)
return 1;
Write8Bit(SLA_WR_address); //从机地址,主机写操作,0x3c
Twi();
Wait(); //0x18,等待发送
if(TestAck()!=TW_MT_SLA_ACK)
return 1;
Write8Bit(wr_address); //发送地址
Twi();
Wait(); //0x28
if(TestAck()!=TW_MT_DATA_ACK)
return 1;
Write8Bit(wr_data); //写数据
Twi();
Wait(); //0x28
if(TestAck()!=TW_MT_DATA_ACK)
return 1;
Stop(); //发送结束信号
delayms(15);
return 0;
}
/**************************************************/
//函数名:I2C_read
//作用:I2C通信中的读操作
uchar I2C_read(uchar SLA_WR_address,uchar SLA_RE_address,uchar re_address)
{
uchar temp;
Start(); //发送开始信号
Wait(); //0x08
if(TestAck()!=TW_START)
return 1;
Write8Bit(SLA_WR_address); //从机地址,主机写操作,0x3c
Twi();
Wait(); //0x18
if(TestAck()!=TW_MT_SLA_ACK)
return 1;
Write8Bit(re_address); //发送地址
Twi();
Wait(); //0x28
if(TestAck()!=TW_MT_DATA_ACK)
return 1;
Start(); //发送开始信号,
Wait(); //0x10
if(TestAck()!=TW_REP_START)
return 1;
Write8Bit(SLA_RE_address); //从机地址,主机读操作,0x3d
Twi();
Wait(); //0x40
if(TestAck()!=TW_MR_SLA_ACK)
return 1;
Twi();
Wait(); //0x58
if(TestAck()!=TW_MR_DATA_NACK)
return 1;
temp = TWDR; //读取数据
Stop();//发送结束信号
delayms(1);
TWCR=0X80;////清除TWINT和禁止TWI(不加上这句程序只能读一次)
return temp;
}
#endif
能不能把GCC环境下的代码共享下啊。 帮楼主项一下,有助温习。 楼主能不能共享下你的代码啊。 seewolf 发表于 2012-9-10 10:57 static/image/common/back.gif
这是我写的I2C通信的头文件,你可以先检查下I2C是不是有问题。我用它调过ADXL345,所以这个头文件保证没错 ...
哈哈!就是接受的一个标志位判断错误了!终于调出来咯!太谢谢你啦!!!!要不然还不知道要花多少时间才能弄出这个来呢………… fanice 发表于 2012-9-22 22:52 static/image/common/back.gif
楼主能不能共享下你的代码啊。
你是要I2C的还是中断的啊? 你是要I2C的还是中断的啊?
我想要I2C的。不使用中断模式。
多谢了!我的邮箱是fanice1979@yahoo.COM.CN wlkobe 发表于 2012-9-25 22:05 static/image/common/back.gif
哈哈!就是接受的一个标志位判断错误了!终于调出来咯!太谢谢你啦!!!!要不然还不知道要花多少时间才 ...
呵呵~没事,能帮上忙就好~ fanice 发表于 2012-9-26 12:49 static/image/common/back.gif
我想要I2C的。不使用中断模式。
多谢了!我的邮箱是
35楼的那个程序就是可以用的,你把那个拷过去就可以了 多谢了。 能不能把你的ATmega16的TWI(I2C)读取MMA7455角加速度的程序发给我啊,十分感谢啊,我的邮箱是lt8603@163.com
学习过了。。。。 已经顺利读出MMA7455的数据,多谢指教。 我也在调MMA7455,能不能加Q指导一下啊,或者发程序到我邮箱QQ615213015,谢谢啊,拜托了 xihudelei 发表于 2012-11-16 12:29 static/image/common/back.gif
我也在调MMA7455,能不能加Q指导一下啊,或者发程序到我邮箱QQ615213015,谢谢啊,拜托了 ...
楼上有相应的程序,是可以用的,你可以试试,如果还不行的话加我Q吧:405519134 atmega16的电压是5V,MMA7455加速计电压最高是3.3,这怎么可以用?是外加电路了么,还有一个问题,外接上拉电阻怎么建立? wlkobe 发表于 2012-9-25 22:05 static/image/common/back.gif
哈哈!就是接受的一个标志位判断错误了!终于调出来咯!太谢谢你啦!!!!要不然还不知道要花多少时间才 ...
能告诉我你是哪个标志位出错了吗?我的也是和你相同的问题 plychoz 发表于 2013-2-19 15:08 static/image/common/back.gif
能告诉我你是哪个标志位出错了吗?我的也是和你相同的问题
我是
uchar f_I2cWrite(uchar Wdata,uchar RegAddress) //I2C总线写一字节返回1:写成功返回0:写失败
{
Start(); //I2C启动
Wait();
if(TestAck()!=START) return 12; //ACK
//uint t=WD_DEVICE_ADDR<<1;
WriteByte(WD_DEVICE_ADDR); //写入I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK) return 2; //ACK
WriteByte(RegAddress); //写相应寄存器地址
Wait();
if(TestAck()!=MT_DATA_ACK) return 3;
WriteByte(Wdata); //写数据
Wait();
if(TestAck()!=MT_SLA_ACK) return 4; //ACK
Stop(); //I2C停止
Delay_ms(10);
return 0;
}
里面的 RETURN 4 的那个标志位错了,改成MT_DATA_ACK 我的芯片外漏接了电容,加上之后,可以读写了。谢谢哈~
你有没有遇到过读XOUT寄存器的值,一直不变的情况呀?我读XOUT寄存器的值时,读数一直是255,也就是说XOUT中的值是原来的默认值0,可以这么理解吗?不知道原因出在哪 楼主,不知道你在16上成功的程序,有没有在mega64上试过,我现在遇到一个情况,就是同样的TWI读写程序,在16上可行,但是在64上调试不成功,好像是发从机地址和写方式的时候反馈不成功~不知道楼主有什么看法? as280711261 发表于 2013-4-13 21:16 static/image/common/back.gif
楼主,不知道你在16上成功的程序,有没有在mega64上试过,我现在遇到一个情况,就是同样的TWI读写程序,在1 ...
MEGA64没有用过,这个问题确实没有遇到过,实在不好意思哦……
按理说这两个单片机模块应该是可以通用的吧? 16和64的TWI接口是通用的,我的问题已经找到了,是硬件上的问题~~ wlkobe 发表于 2012-9-25 22:05 static/image/common/back.gif
你是要I2C的还是中断的啊?
楼主最后是怎么解决的啊,我也是读的时候
Start(); //I2C启动
Wait();
if(TestAck()!=START)
return 1; //ACK
返回1. Simon41 发表于 2013-6-11 14:45 static/image/common/back.gif
楼主最后是怎么解决的啊,我也是读的时候
已解决,上拉电阻的问题
页:
[1]