基于STM32的IIC总线设计.docx
- 文档编号:4456870
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:18
- 大小:101.33KB
基于STM32的IIC总线设计.docx
《基于STM32的IIC总线设计.docx》由会员分享,可在线阅读,更多相关《基于STM32的IIC总线设计.docx(18页珍藏版)》请在冰豆网上搜索。
基于STM32的IIC总线设计
基于STM32的IIC总线设计
摘要:
在需要远距离传输数据,而且布线不方便的情况下使用IIC总线能解决这个问题。
本文通过IIC总线将从机AD采样的数据存储到EEPROM芯片里面,同时,通过IIC总线将存储的数据给其他单片机使用,并用STM32开发板进行了实验仿真。
关键词:
IIC总线EEPROMARM单片机
1引言
随着大规模集成电路技术的发展,把CPU和一个单独工作系统所必需的ROM、RAM、I/O端口、A/D、D/A等外围电路集成在一个单片而制成的单片机或微控制器愈来愈方便。
目前,世界上许多公司生产单片机,品种很多。
其中包括各种字长的CPU,各种容量的ROM、RAM以及功能各异的I/O接口电路等等,但是,单片机的品种规格仍然有限,所以只能选用某种单片机来进行扩展。
扩展的方法有两种:
一种是并行总线,另一种是串行总线[1]。
由于串行总线的连线少,结构简单,往往不用专门的母板和插座而直接用导线连接各个设备。
因此,采用串行线可大大简化系统的硬件设计。
PHILIPS公司早在十几年前就推出了I2C串行总线,利用该总线可实现多主机系统所需的裁决和高低速设备同步等功能。
IIC即Inter-IntegratedCircuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS),IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源[2]。
这种方式简化了信号传输总线接口。
2方案设计
IIC总线
图一方案原理图
通过AD采样将我们收集到的数据输入给单片机,经过单片机处理后经IIC总线把数据存储到芯片里面,方便给其他单片机使用。
由于使用的是IIC总线,只需要两根线,大大节约了成本,而且方便布线。
3工作原理
物理结构上,IIC系统由一条串行数据线SDA和一条串行时钟线SCL组成。
主机按一定的通信协议向从机寻址和进行信息传输。
在数据传输时,由主机初始化一次数据传输,主机使数据在SDA线上传输的同时还通过SCL线传输时钟。
信息传输的对象和方向以及信息传输的开始和终止均由主机决定。
每个器件都有一个唯一的地址,而且可以是单接收的器件或者可以接收也可以发送的器件。
发送器或接收器可以在主模式或从模式下操作,这取决于芯片是否必须启动数据的传输还是仅仅被寻址。
一般情况下,一个标准的IIC通信由四部分组成:
开始信号、从机地址传输、数据传输、停止信号。
由主机发送一个开始信号,启动一次IIC通信;在主机对从机寻址后,再在总线上传输数据。
IIC总线上传送的每一个字节均为8位,首先发送的数据位为最高位,每传送一个字节后都必须跟随一个应答位,每次通信的数据字节数是没有限制的;在全部数据传送结束后,由主机发送停止信号,结束通信。
4硬件设计
需要用到的硬件有STM32芯片,本次设计仿真所用的是STM32F103RCT6,同时还需要EEPROM存储芯片,选择的是24C02这款芯片,为了显示是否发送成功增加量LCD显示屏,仿真平台为miniSTM32开发版。
其中,硬件连接图见图2。
图二STM32与24C02连接图
A0、A1、A2为器件的地址选择,GND接地,VCC工作电压-1.8V-6V,WP为写保护,5、6引脚即IIC总线的时钟线和数据线[4]。
5程序设计
5.1ADC初始化
图三ADC初始化流程图
ADC初始化流程图如图三所示。
本文采用了定时采样,为了方便设置为10微秒,由于stm32的采样时间没有刚好等于10微秒的,所以用了71.5的采样周期加上固定的12.5个周期,选用72M6分频得到采样时间为7微秒,再延时3微秒实现要求值。
5.2存储与读取数据
首先,IIC工作前需要驱动代码。
其中包括IIC初始化、IIC开始、IIC结束、ACK、IIC读写等功能。
主函数工作之前需要初始化的有延时、串口、IIC等,通过按键来切换选择读取还是写入,其具体代码见附录。
读取和存储数据流程图见图四:
N
Y
图四读写和存储数据流程图
6总结
特点:
1)IIC总线只要求两条总线线路,一条串行数据线SDA,一条串行时钟线SCL。
布线方便
2)每个连接到总线的器件都可以通过设定唯一的地址进行数据交换。
3)传输距离远,适合于远距离布线。
缺点:
1)从机的数量收到限制。
2)总线上主机过多会导致数据冲突效率不高。
改进:
1)如果两个或更多主机同时初始化数据传输可以通过冲突检测和仲裁防止数据被破坏。
2)可以和智能仪表相连构建现场IIC总线系统。
3)将单纯的单片机改变成智能单片机实现智能化。
4)多种总线接口联合在一起再和英特网相连实现工业物联网系统[5]。
7参考文献
[1]光建,贾金玲,基于单片机12C总线系统设计[J].仪器仪表学报,2006,27(6):
2466-2472
[2]何立民.IIC总线应用系统设计[M].:
航空航天大学,1995
[3]周立功,华.深入浅出ARM[M].:
航空航天大学.2006:
1-161.
[4]洋,原子教你玩STM32[M].航空航天大学,2013.4
[5]雷林,基于internet和现场总线的测控系统研究[J].仪器仪表学报,2012,23(z2):
690-691
8附录
程序
主函数
#include"led.h"
#include"delay.h"
#include"sys.h"
#include"usart.h"
#include"lcd.h"
#include"key.h"
#include"24cxx.h"
#include"myiic.h"
constu8TEXT_Buffer[]={"MiniSTM32IICTEST"};
#defineSIZEsizeof(TEXT_Buffer)
intmain(void)
{
u8key;
u16i=0;
u8datatemp[SIZE];
NVIC_Configuration();
delay_init();//延时函数初始化
uart_init(9600);//串口初始化为9600
LED_Init();//初始化与LED连接的硬件接口
LCD_Init();
KEY_Init();//按键初始化
AT24CXX_Init();//IIC初始化
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(60,50,200,16,16,"MiniSTM32");
LCD_ShowString(60,70,200,16,16,"IICTEST");
LCD_ShowString(60,90,200,16,16,"ATOMALIENTEK");
LCD_ShowString(60,110,200,16,16,"2014/3/9");
LCD_ShowString(60,130,200,16,16,"WK_UP:
WriteKEY0:
Read");//显示提示信息
while(AT24CXX_Check())//检测不到24c02
{
LCD_ShowString(60,150,200,16,16,"24C02CheckFailed!
");
delay_ms(500);
LCD_ShowString(60,150,200,16,16,"PleaseCheck!
");
delay_ms(500);
LED0=!
LED0;//DS0闪烁
}
LCD_ShowString(60,150,200,16,16,"24C02Ready!
");
POINT_COLOR=BLUE;//设置字体为蓝色
while
(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES)//WK_UP按下,写入24C02
{
LCD_Fill(0,170,239,319,WHITE);//清除半屏
LCD_ShowString(60,170,200,16,16,"StartWrite24C02....");
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
LCD_ShowString(60,170,200,16,16,"24C02WriteFinished!
");//提示传送完成
}
if(key==KEY0_PRES)//KEY0按下,读取字符串并显示
{
LCD_ShowString(60,170,200,16,16,"StartRead24C02....");
AT24CXX_Read(0,datatemp,SIZE);
LCD_ShowString(60,170,200,16,16,"TheDataReadedIs:
");//提示传送完成
LCD_ShowString(60,190,200,16,16,datatemp);//显示读到的字符串
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!
LED0;//提示系统正在运行
i=0;
}
}
}
ADC初始化代码
voidAdc_Init(void)
{
ADC_InitTypeDefADC_InitStructure;
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);//使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//设置ADC分频因子672M/6=12,ADC最大时间不能超过14M
//PA1作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//模拟输入引脚
GPIO_Init(GPIOA,&GPIO_InitStructure);
ADC_DeInit(ADC1);//复位ADC1,将外设ADC1的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//ADC工作模式:
ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode=DISABLE;//模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel=1;//顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1,&ADC_InitStructure);//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1,ENABLE);//使能指定的ADC1
ADC_ResetCalibration(ADC1);//使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束
ADC_StartCalibration(ADC1);//开启AD校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准结束
//ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能指定的ADC1的软件转换启动功能
}
//获得ADC值
//ch:
通道值0~3
u16Get_Adc(u8ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_71Cycles5);//ADC1,ADC通道,采样时间为71.5周期
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能指定的ADC1的软件转换启动功能
while(!
ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换结束
delay_us(3);
returnADC_GetConversionValue(ADC1);//返回最近一次ADC1规则组的转换结果
}
IIC子程序
#include"myiic.h"
#include"delay.h"
//初始化IIC
voidIIC_Init(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
//RCC->APB2ENR|=1<<4;//先使能外设IOPORTC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
IIC_SCL=1;
IIC_SDA=1;
}
//产生IIC起始信号
voidIIC_Start(void)
{
SDA_OUT();//sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:
whenCLKishigh,DATAchangeformhightolow
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
voidIIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:
whenCLKishighDATAchangeformlowtohigh
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:
1,接收应答失败
//0,接收应答成功
u8IIC_Wait_Ack(void)
{
u8ucErrTime=0;
SDA_IN();//SDA设置为输入
IIC_SDA=1;delay_us
(1);
IIC_SCL=1;delay_us
(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return1;
}
}
IIC_SCL=0;//时钟输出0
return0;
}
//产生ACK应答
voidIIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us
(2);
IIC_SCL=1;
delay_us
(2);
IIC_SCL=0;
}
//不产生ACK应答
voidIIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us
(2);
IIC_SCL=1;
delay_us
(2);
IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
voidIIC_Send_Byte(u8txd)
{
u8t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;
txd<<=1;
delay_us
(2);//对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us
(2);
IIC_SCL=0;
delay_us
(2);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8IIC_Read_Byte(unsignedcharack)
{
unsignedchari,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++)
{
IIC_SCL=0;
delay_us
(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us
(1);
}
if(!
ack)
IIC_NAck();//发送nACK
else
IIC_Ack();//发送ACK
returnreceive;
}
24C02子程序
#include"24cxx.h"
#include"delay.h"
//初始化IIC接口
voidAT24CXX_Init(void)
{
IIC_Init();
}
//在AT24CXX指定地址读出一个数据
//ReadAddr:
开始读数的地址
//返回值:
读到的数据
u8AT24CXX_ReadOneByte(u16ReadAddr)
{
u8temp=0;
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0);//发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址
IIC_Wait_Ack();
}elseIIC_Send_Byte(0XA0+((ReadAddr/256)<<1));//发送器件地址0XA0,写数据
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr%256);//发送低地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(0XA1);//进入接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
returntemp;
}
//在AT24CXX指定地址写入一个数据
//WriteAddr:
写入数据的目的地址
//DataToWrite:
要写入的数据
voidAT24CXX_WriteOneByte(u16WriteAddr,u8DataToWrite)
{
IIC_Start();
if(EE_TYPE>AT24C16)
{
IIC_Send_Byte(0XA0);//发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址
}else
{
IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));//发送器件地址0XA0,写数据
}
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr%256);//发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite);//发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
delay_ms(10);
}
//在AT24CXX里面的指定地址开始写入长度为Len的数据
//该函数用于写入16bit或者32bit的数据.
//WriteAddr:
开始写入的地址
//DataToWrite:
数据数组首地址
//Len:
要写入数据的长度2,4
voidAT24CXX_WriteLenByte(u16WriteAddr,u32DataToWrite,u8Len)
{
u8t;
for(t=0;t { AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff); } } //在AT24CXX里面的指定地址开始读出长度为Len的数据 //该函数用于读出16bit或者32bit的数据. //ReadAddr: 开始读出的地址 //返回值: 数据 //Len: 要读出数据的长度2,4 u32AT24CXX_ReadLenByte(u16ReadAddr,u8Len) { u8t; u32temp=0; for(t=0;t { temp<<=8; temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1); } returntemp; } //检查AT24CXX是否正常 //这里用了24XX的最后一个地址(255)来存储标志字. //如果用其他24C系列,这个地址要修改 //返回1: 检测失败 //返回0: 检测成功 u8AT24CXX_Check(void) { u8temp; temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX if(temp==0X55)return0; else//排除第一次初始化的情况 { AT
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 STM32 IIC 总线 设计