首先,iic做从机的程序源码网上比较多,我就不发了,说下调试方法。
相信主机部分已经调试通过了,在这个前提下,楼主的思路是没错的,接收非空,读数据。iic属于一个硬件接口,出问题的时候需要借助示波器,监测每个时候每个数据的波形,同时用JTAG在线调试,分析从机相关寄存器的状态,与自己计算的理论值做对比看是否正确,最终会找到一个出错的地方,看着一堆数据确实会枯燥一些,楼主加油,祝成功~
JTAG(Joint Test Action Group;联合测试行动小组)是一种国际标准测试协议(IEEE 11491兼容),主要用于芯片内部测试。现在多数的高级器件都支持JTAG协议,如DSP、FPGA器件等。标准的JTAG接口是4线:TMS、TCK、TDI、TDO,分别为模式选择、时钟、数据输入和数据输出线。
UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。
Jtag用的比较多的是单片机的在线仿真,当然也有ISP在线仿真的。UART主要是用作串口通信的,还有一种SPI通信。当然IIC也是常用的协议。 以后学到了就明白了。可以看看郭天祥的51视频教程。
我们平时用keil主要是编程,生产hex文件,然后根据不同的单片机选择不同的下载软件。比如STC89S52的单片机,就用STC_ISP这个软件下载程序的。如果是AT89c51的单片机,又要用不同的下载程序了。Atmel公司的51没用过,所以不是很清楚。
此测试程序是先写后读,已经测度通过,希望对你有用!!! /
24c02测试程序 20111201 wqz
/
#include<reg52h>
#include<intrinsh>typedef unsigned char uchar;#define delay5us() _nop_();_nop_();_nop_();_nop_();_nop_();
// _nop_();_nop_();_nop_();_nop_();_nop_(); //延时sbit SDA=P2^7; //IIC总线
sbit SCL=P2^6;
sbit IO =P1^7; //595控制信号
sbit RLK =P1^6;
sbit CLK =P1^5;void my_delay1ms(int t); //晶振频率为110592时,延时为1ms
void Start(); //起始信号
void stop(); //结束信号
void ACK(); //写应答
bit test(); //测试应答信号
void nn(); //不应答
void write_1byte(uchar num);//写一字节数据
uchar read_1byte(); //读一字节数据
uchar write_data(uchar addr,uchar Data,uchar num); //将数据写入24C02中
void write_mpage(uchar addr,uchar Data,uchar num); //页写
void read_data(uchar addr,uchar p,uchar num2); //从24C02中读出数据/
主函数
/void main()
{
uchar i,j,aa; uchar dis1[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,<br> 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0--F
uchar dis2[16]; //将dis1中的数据写入24C02后读出存在dis2中
write_mpage(0,dis1,16); //写
my_delay1ms(10);
read_data(0,dis2,16); // 读
my_delay1ms(10); while(1)
{
for(j=0;j<16;j++) //将读出的数据显示在数码管上,测试正确性
{
aa=dis2[j];
RLK=0;
for(i=0;i<8;i++)
{
aa<<=1;
IO=CY;
CLK=0;
CLK=1;
}
RLK=1;
my_delay1ms(2000);
}
}
}//void my_delay1ms(int t) //晶振频率为110592时,延时为1ms
{
uchar i,j; while(t--)
{
for(i=10;i>0;i--)
for(j=41;j>0;j--);
}
}//void Start() //起始信号
{
SDA=1;
SCL=1;
delay5us();
SDA=0;
delay5us();
SCL=0;
delay5us();
SDA=1;
}//void stop() //结束信号
{
SDA=0;
delay5us();
SCL=0;
SCL=1;
delay5us();
SDA=1;
}//void ACK() //写应答
{
SDA=0;
SCL=1;
delay5us();
SCL=0;
delay5us();
SDA=1;
}//bit test() //测试应答信号
{
bit a; SDA=1;
delay5us();
SCL=1;
a=SDA;
SCL=0;
return(a);
}//void nn() //不应答
{
SDA=1;
SCL=0;
delay5us();
SCL=1;
}//void write_1byte(uchar num)//写一字节数据
{
uchar i,date; date=num;
for(i=0;i<8;i++)
{
date<<=1;
SDA=CY;
delay5us();
SCL=1;
delay5us();
SCL=0;
}
}//uchar read_1byte() //读一字节数据
{
uchar i,tember=0; for (i=0;i<8;i++)
{
tember<<=1;
if(SDA)
tember|=0x01;
SCL=1;
delay5us();
SCL=0;
}
return tember;
}//uchar write_data(uchar addr,uchar Data,uchar num) //将数据写入24C02中
{
uchar i,diz; diz=addr;
Start();
write_1byte(0xa0);
test();
write_1byte(diz);
test();
for(i=0;i<num;)
{
write_1byte(Data++);
test();
i++;
diz++;
if((diz&0x07)==0) break;
}
stop();
return (num-i);
}//void write_mpage(uchar addr,uchar Data,uchar num) //页写
{
uchar ff; ff=num;
do
{
ff=write_data( addr+(num-ff),Data+(num-ff),ff);
my_delay1ms(10);
}
while(ff);
}//void read_data(uchar addr,uchar p,uchar num2) //从24C02中读出数据
{
uchar i; Start();
write_1byte(0xa0);
test();
write_1byte(addr);
test();
Start();
write_1byte(0xa1);
test();
for(i=0;i<num2-1;i++)
{
p++=read_1byte();
ACK();
}
p=read_1byte();
nn();
stop();
}
其实程序是一模一样的,唯一的区别是模拟IIC需要CPU运算,这样就增加了单片机的运算时间,而带IIC接口的单片机,程序还是需要的,但是IIC的运算通过集成在单片机里面的寄存器硬件电路来运算,就像定时器电路一样自己会运算,这样就不要cpu来运算过程了,从而节省了时间,使cpu运算的更快。当然这样就的多付出经济成本哦
51 单片机的引脚,输出 1 的能力很差。
这时,引脚的电压,取决于外来的信号。
输出 1,就是设置为输入状态。就是准备读取数据。
8次循环后,dat即为 IIC 器件送来的数据。
IIC不是单总线,你别搞错了DS18B20是单总线没错这两个芯片是不能主动发数据的两者都是要向芯片写指令然后读取数据,IIC有专门的通信协议DS18B20也要遵照其单总线协议才能通信,具体请下载对应的Datasheet看看这里给你发个DS18B20的,IIC的你再搜索一下吧,网上大把的
用串口显示的
#include <REG52H>
#include <mathh> //Keil library
#include <stdioh> //Keil library
#include <INTRINSH>
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
//
// 定义51单片机端口
//
#define DataPort P0 //LCD1602数据端口
sbit SCL=P1^0; //IIC时钟引脚定义
sbit SDA=P1^1; //IIC数据引脚定义
sbit LCM_RS=P2^0; //LCD1602命令端口
sbit LCM_RW=P2^1; //LCD1602命令端口
sbit LCM_EN=P2^2; //LCD1602命令端口
//
// 定义MPU6050内部地址
//
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
//
//定义类型及变量
//
uchar dis[6]; //显示数字(-511至512)的字符数组
int dis_data; //变量
//int Temperature,Temp_h,Temp_l; //温度及高低位数据
//
//函数声明
//
void delay(unsigned int k); //延时
void lcd_printf(uchar s,int temp_data);
//MPU6050 *** 作函数
void InitMPU6050(); //初始化MPU6050
void Delay5us();
void I2C_Start();
void I2C_Stop();
void I2C_SendACK(bit ack);
bit I2C_RecvACK();
void I2C_SendByte(uchar dat);
uchar I2C_RecvByte();
void I2C_ReadPage();
void I2C_WritePage();
void display_ACCEL_x();
void display_ACCEL_y();
void display_ACCEL_z();
uchar Single_ReadI2C(uchar REG_Address); //读取I2C数据
void Single_WriteI2C(uchar REG_Address,uchar REG_data); //向I2C写入数据
//
//整数转字符串
//
void lcd_printf(uchar s,int temp_data)
{
if(temp_data<0)
{
temp_data=-temp_data;
s='-';
}
else s=' ';
++s =temp_data/10000+0x30;
temp_data=temp_data%10000; //取余运算
++s =temp_data/1000+0x30;
temp_data=temp_data%1000; //取余运算
++s =temp_data/100+0x30;
temp_data=temp_data%100; //取余运算
++s =temp_data/10+0x30;
temp_data=temp_data%10; //取余运算
++s =temp_data+0x30;
}
//
void SeriPushSend(uchar send_data)
{
SBUF=send_data;
while(!TI);TI=0;
}
//
//延时
//
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;i++)
{
for(j=0;j<121;j++);
}
}
//
//延时5微秒(STC90C52RC@12M)
//不同的工作环境,需要调整此函数
//当改用1T的MCU时,请调整此延时函数
//
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
//
//I2C起始信号
//
void I2C_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
//
//I2C停止信号
//
void I2C_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
//
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//
void I2C_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
//
//I2C接收应答信号
//
bit I2C_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
//
//向I2C总线发送一个字节数据
//
void I2C_SendByte(uchar dat)
{
uchar i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
I2C_RecvACK();
}
//
//从I2C总线接收一个字节数据
//
uchar I2C_RecvByte()
{
uchar i;
uchar dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
//
//向I2C设备写入一个字节数据
//
void Single_WriteI2C(uchar REG_Address,uchar REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //内部寄存器地址,
I2C_SendByte(REG_data); //内部寄存器数据,
I2C_Stop(); //发送停止信号
}
//
//从I2C设备读取一个字节数据
//
uchar Single_ReadI2C(uchar REG_Address)
{
uchar REG_data;
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号
REG_data=I2C_RecvByte(); //读出寄存器数据
I2C_SendACK(1); //接收应答信号
I2C_Stop(); //停止信号
return REG_data;
}
//
//初始化MPU6050
//
void InitMPU6050()
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态
Single_WriteI2C(SMPLRT_DIV, 0x07);
Single_WriteI2C(CONFIG, 0x06);
Single_WriteI2C(GYRO_CONFIG, 0x18);
Single_WriteI2C(ACCEL_CONFIG, 0x01);
}
//
//合成数据
//
int GetData(uchar REG_Address)
{
uchar H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L; //合成数据
}
//
//在1602上显示10位数据
//
void Display10BitData(int value,uchar x,uchar y)
{ uchar i;
// value/=64; //转换为10位数据
lcd_printf(dis, value); //转换数据显示
for(i=0;i<6;i++)
{
SeriPushSend(dis[i]);
}
// DisplayListChar(x,y,dis,4); //启始列,行,显示数组,显示长度
}
//
//显示温度
//
//void display_temp()
//{
// Temp_h=Single_ReadI2C(TEMP_OUT_H); //读取温度
// Temp_l=Single_ReadI2C(TEMP_OUT_L); //读取温度
// Temperature=Temp_h<<8|Temp_l; //合成温度
// Temperature = 35+ ((double) (Temperature + 13200)) / 280; // 计算出温度
// lcd_printf(dis,Temperature); //转换数据显示
// DisplayListChar(11,1,dis,4); //启始列,行,显示数组,显示位数
//}
void init_uart()
{
TMOD=0x21;
TH1=0xfd;
TL1=0xfd;
SCON=0x50;
PS=1; //串口中断设为高优先级别
TR0=1; //启动定时器
TR1=1;
ET0=1; //打开定时器0中断
ES=1;
EA=1;
}
//
//主程序
//
void main()
{
delay(500); //上电延时
// InitLcd(); //液晶初始化
init_uart();
InitMPU6050(); //初始化MPU6050
delay(150);
while(1)
{
Display10BitData(GetData(ACCEL_XOUT_H),2,0); //显示X轴加速度
Display10BitData(GetData(ACCEL_YOUT_H),7,0); //显示Y轴加速度
Display10BitData(GetData(ACCEL_ZOUT_H),12,0); //显示Z轴加速度
Display10BitData(GetData(GYRO_XOUT_H),2,1); //显示X轴角速度
Display10BitData(GetData(GYRO_YOUT_H),7,1); //显示Y轴角速度
Display10BitData(GetData(GYRO_ZOUT_H),12,1); //显示Z轴角速度
SeriPushSend(0x0d);
SeriPushSend(0);//换行,回车
delay(100);
}
}
以上就是关于stm8 硬件i2c从机接收程序全部的内容,包括:stm8 硬件i2c从机接收程序、什么是JTAG协议和UART协议两者有什么不同之处拿Keil这个软件向C51单片机中下载程序为例说明一下、有没有单片机程序,是把IIC的数据读出来。是有应答的。。具体还没想到思路,还想有人执教一下等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)