《我的嵌入式开发》---- IIC 通信
IIC 通用文件,文件是在NRF51xx 芯片基础,keil 平台开发测试通过,后期修改为STM32F2xx系列的配置。
文件百度云盘链接 : https://pan.baidu.com/s/1AFxanwzrAViaubtERZMRsA
注意:在用于STM32Fx 系列时注意引脚读取函数的选择!
下面是示波器现实,IIC通讯读的操作。
理论基础:
- SCL为高,SDA发生变化,即为发生了特殊状态(ACK, NACK, START, STOP)
- SCL为低,SDA发生变化,即为数据端发生跳变,这个是无影响的。
- IIC总线在数据传输时,时钟信号为高电平,数据线上的数据必须保持稳定,只有在SCL上的信号为低电平时,SDA线才允许变
IIC_confing.h 主要是SIMU_IIC.c 文件的一些结构体和端口设置, I2c_Str 结构体可以再添加数据属性,包括后期的数据,主要用于 SIMU_IIC.c 文件内部使用。
/**************************************************************************//**
* @file IIC_confing.h
* @brief For IIC communication
* @author ning lv
* @version 0.01
******************************************************************************
* @section License
******************************************************************************
*
*****************************************************************************/ #ifndef _I2C_CONFING_H_
#define _I2C_CONFING_H_ #ifdef __cplusplus
extern "C" {
#endif #include "SIMU_IIC.h"
/*
*** You can choose yours projects ...*/
//#define NRF51822 //试用在蓝牙芯片上
#define STM32F205 // /*
*** Redefines the exact width signed integer type ...*/
//typedef unsigned char uint8;
//typedef unsigned int uint32;
//typedef signed char uint8_t; /*
*** Define variables and structures ... */
typedef struct {
uint32 SDA;
uint32 SCL;
uint32 GPIO;
}I2c_Str; /*
***The global variable ... */
I2c_Str type_Struct; //all
//sda \ scl
typedef void(*pI2cLineF)(uint32 sda,uint32 scl);
pI2cLineF _I2cLine = _NULL;
// gpio
typedef void(*pI2cGpioF)(uint32 gpo);
pI2cGpioF _I2cGpio = _NULL;
/*
***Chip selection ... */
#if defined NRF51822
#define CHOOSE_IN _TRUE
#define CHOOSE_OUT _NULL
#elif defined STM32F205
#define CHOOSE_IN (GPIO_Mode_IN )
#define CHOOSE_OUT (GPIO_Mode_OUT)
#define GPIO_PORT ((GPIO_TypeDef*)type_Struct.GPIO)
#endif /*
***Output 0/1 ... */
#define SDA_OUT_H ( Gpio_Pin_Wr(type_Struct.SDA,_TRUE) )
#define SDA_OUT_L ( Gpio_Pin_Wr(type_Struct.SDA,_NULL) )
#define SCL_OUT_H ( Gpio_Pin_Wr(type_Struct.SCL,_TRUE) )
#define SCL_OUT_L ( Gpio_Pin_Wr(type_Struct.SCL,_NULL) ) /*
***Choose output/input ... */
#define SDA_SET_IN ( I2c_Pin_Dir (type_Struct.SDA,CHOOSE_IN) )
#define SDA_SET_OUT ( I2c_Pin_Dir (type_Struct.SDA,CHOOSE_OUT) )
#define SCL_SET_IN_ ( I2c_Pin_Dir (type_Struct.SCL,CHOOSE_IN) )
#define SCL_SET_OUT ( I2c_Pin_Dir (type_Struct.SCL,CHOOSE_OUT) )
/*
*** Reads lines ... */
#define RD_SDA_IN ( Gpio_Pin_Red(type_Struct.SDA) )
#define RD_SCL_IN ( Gpio_Pin_Red(type_Struct.SCL) ) /*
*** times ... */
#define NOP() ( __nop() )
#define Iic_Delay(x) ( delay_us(x) ) #ifdef __cplusplus
}
#endif
#endif /*_I2C_CONFING_H_*/SIMU_IIC.c 文件主要的运行文件,开头是所需的芯片头文件,特别注意的是delay_ms();和delay_us();两个函数要根据芯片的不同,配置设备的不同定向修改,修改的过程中可以用示波器具体调试时间。
//Header files ...
#include "IIC_confing.h" //master and the explanation is here!!
#include "usart.h" //Chip selection ...
#if defined NRF51822
#include "nrf_gpio.h"
#elif defined STM32F205
#include <stm32f2xx_gpio.h>
#endif /*
***Function declaration ...*/
void Delay5us(void);
void Delay5us(void);
void Delay10us(void);
void Gpio_Pin_Wr(uint32 pin ,uint8 wr);
void I2c_Pin_Dir(uint32 pin, uint8 dir);
void Choose_I2c_Pin(uint32 sda,uint32 scl);
void Gpio_Confing(uint32 gpo); //下面的可以发布在IIC.h 函数中,对外的接口设置
void I2c_Stop(void);
void I2c_NoAck(void);
void I2c_RecAck(void);
void I2c_Reset (void);
uint8 I2c_Start(void);
uint8 I2c_WaitACK(void);
uint8 I2c_RcvByte(void);
void I2c_SendByte(uint8 c);
uint8 Gpio_Pin_Red(uint32 pin);
void IIC_confing_Pin(uint32 sda,uint32 scl, uint32 gpo);
void delay_ms(uint32 volatile number_of_ms);
void delay_us(uint32 volatile number_of_us); /**@brief Delay 1us
*/
void Delay1us(void)
{
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
#if defined STM32F205
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
NOP();NOP();NOP();NOP();
#endif
}
/**@brief Delay 5us
*/
void Delay5us(void)
{
Delay1us();
Delay1us();
Delay1us();
Delay1us();
} /**@brief Delay 10us
*/
void Delay10us(void)
{
Delay5us();
Delay5us();
} /**@brief Delay(ms)
*
* @param[in] number_of_ms
*/
void delay_ms(uint32 volatile number_of_ms)
{
number_of_ms = number_of_ms * ;
while(number_of_ms != )
{
number_of_ms--;
Delay1us();
}
} /**@brief Delay(us)
*
* @param[in] number_of_us
*/
void delay_us(uint32 volatile number_of_us)
{
while(number_of_us != )
{
number_of_us--;
Delay1us(); }
} /**@brief Select the I2C sda and scl pins.
*/
void Choose_I2c_Pin( uint32 sda,uint32 scl )
{
type_Struct.SDA = sda;
type_Struct.SCL = scl;
} /**@brief Function Pointers set GPIO
*/
void Gpio_Confing( uint32 gpo )
{
type_Struct.GPIO = gpo;
} /**@brief Function Pointers set the sda and SCL pins
*/
void IIC_confing_Pin( uint32 sda,uint32 scl, uint32 gpo)
{
#if defined STM32F205
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
#endif
_I2cGpio = (pI2cGpioF)Gpio_Confing;
_I2cGpio(gpo); _I2cLine = (pI2cLineF)Choose_I2c_Pin ;
_I2cLine(sda,scl);
} /**@brief Iic_Pin_Dir 支持文件 STM32F2xx or NRF51822
*
* @param[in] dir
*/
#if defined ( STM32F205 )
void STM32F205_Pin_Dir (uint32 pin, uint8 dir)
{
GPIO_InitTypeDef GPIO_InitStructure;
if(GPIO_Mode_OUT == dir){
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
}else if(GPIO_Mode_IN == dir){
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
}
GPIO_InitStructure.GPIO_Pin = pin;
GPIO_Init(GPIO_PORT, &GPIO_InitStructure);
}
#elif defined ( NRF51822 )
void nRF51822_Pin_Dir (uint32 pin, uint8 dir)
{
if ( dir == ) {
nrf_gpio_cfg_output(pin);
}else {
nrf_gpio_cfg_input(pin,NRF_GPIO_PIN_PULLUP);
}
}
#endif /**@brief The pin line outputs 0/1.
*
* @param[in] dir
*/
void I2c_Pin_Dir (uint32 pin, uint8 dir)
{
#if defined ( NRF51822 )
nRF51822_Pin_Dir (pin, dir);
#elif defined ( STM32F205 )
STM32F205_Pin_Dir (pin, dir);
#endif
} /**@brief SDA/SCL line write 0/1.
*
* @param[in] pin ,wr
*/ void Gpio_Pin_Wr(uint32 pin ,uint8 wr)
{
if ( wr == ) {
#if defined ( NRF51822 )
nrf_gpio_pin_write(pin,);
#elif defined ( STM32F205 )
GPIO_WriteBit(GPIO_PORT , pin , );
#endif
}
else {
#if defined ( NRF51822 )
nrf_gpio_pin_write(pin,);
#elif defined ( STM32F205 )
GPIO_WriteBit(GPIO_PORT , pin , );
#endif
}
} /**@brief SDA/SCL line read 0/1.
*
* @param[in] pin
*/
uint8 Gpio_Pin_Red(uint32 pin)
{
#if defined ( NRF51822 )
return ((uint8) nrf_gpio_pin_read(pin));
#elif defined ( STM32F205 )
return (uint8) GPIO_ReadInputDataBit(GPIO_PORT , pin);
#endif
} /**@brief IIC communication to prepare.
*
* @param[in] i2c_master
*/
uint8 I2c_Start(void)
{
/* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
I2c_Reset(); SCL_SET_OUT;
SDA_SET_OUT; SDA_OUT_H;
SCL_OUT_H;
Iic_Delay(I2C_DELAY_TM);
if( !RD_SDA_IN ) {
return I2C_BUSY; //BUSY
}
SDA_OUT_L;
Iic_Delay(I2C_DELAY_TM);
if( RD_SDA_IN ) {
return I2C_ERROR; //ERROR
}
SDA_OUT_L;/*CPU占线*/
return I2C_TRUE;
} /**@brief IIC stop the communication .
*
* @param[in] i2c_master
*/
void I2c_Stop(void)
{
/* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */
SCL_OUT_L;
Iic_Delay(I2C_DELAY_TM);
SDA_OUT_L;
Iic_Delay(I2C_DELAY_TM);
SCL_OUT_H;
Iic_Delay(I2C_DELAY_TM);
SDA_OUT_H;
} /**@brief reset
*/
void I2c_Reset (void)
{
if( RD_SDA_IN ==
//|| READ_SCL_IN == 0
)
{
SCL_SET_OUT;
SDA_SET_OUT;
Iic_Delay(I2C_DELAY_TM); SDA_OUT_H;
SCL_OUT_H;
Iic_Delay(I2C_DELAY_TM); I2c_SendByte(0xFF);
I2c_NoAck();
I2c_Stop();
}
}
/**@brief Send the data 'c' out,either as data or as an address.
*
* @param[in] C
*/
void I2c_SendByte(uint8 c)
{
uint8 i;
i = ; while(i--)
{
SCL_OUT_L; /*允许SDA 数据跳变*/
Iic_Delay(I2C_DELAY_TM);
if( c&0x80) {
SDA_OUT_H;
}
else {
SDA_OUT_L;
} c<<=;
SCL_OUT_H; /*SDA 数据保持 1us*/
Iic_Delay(I2C_DELAY_TM);
}
SCL_OUT_L;
SDA_OUT_H; /*CPU 释放总线*/
} /**@brief Reads a bytes of data and returns it.
*
* @param[out] retc
*/
uint8 I2c_RcvByte(void)
{
uint8 i = ;
uint8 retc = ; SDA_SET_IN;
SDA_OUT_L;/*总线默认拉高*/
while(i--)
{
retc<<=;
SCL_OUT_L; /*CPU 允许 SDA 数据跳变*/
Iic_Delay(I2C_DELAY_TM);
SCL_OUT_H; /*CPU 保持 SDA 数据1us*/
Iic_Delay(I2C_DELAY_TM);
if( RD_SDA_IN ) {
retc |= 0x01;
}
}
SCL_OUT_L;
SDA_SET_OUT;
SDA_OUT_H; /*CPU 释放总线*/ return retc;
}
/**@brief watint ACK
*/
uint8 I2c_WaitACK(void)
{
uint8 errTime = ;
uint8 retFlag = I2C_TRUE; SCL_OUT_L;
SDA_OUT_H; /*CPU 释放总线*/
Iic_Delay(I2C_DELAY_TM); SCL_OUT_H; /*CPU驱动SCL = 1, 此时器件会返回ACK应答*/
SDA_SET_IN;
Iic_Delay(I2C_DELAY_TM);
while((RD_SDA_IN)&&((errTime--) > ))
{
if(errTime == ){
retFlag = I2C_FALSE;
}
}
SCL_OUT_L;
SDA_SET_OUT;
return retFlag;
}
/**@brief ACK response
*/
void I2c_RecAck(void)
{
SCL_OUT_L; /*CPU 允许 SDA 数据跳变*/
Iic_Delay(I2C_DELAY_TM);
SDA_OUT_L; /*CPU 拉低SDA ,ACK器件*/
Iic_Delay(I2C_DELAY_TM);
SCL_OUT_H; /*CPU 保持 SDA 数据1us*/
Iic_Delay(I2C_DELAY_TM);
SCL_OUT_L;
Iic_Delay(I2C_DELAY_TM);
SDA_OUT_H; /* CPU释放SDA总线 */
} /**@brief Don't reply
*/
void I2c_NoAck(void)
{
SCL_OUT_L;
Iic_Delay(I2C_DELAY_TM);
SDA_OUT_H;
Iic_Delay(I2C_DELAY_TM);
SCL_OUT_H;
Iic_Delay(I2C_DELAY_TM);
SCL_OUT_L;
Iic_Delay(I2C_DELAY_TM);
}SIMCU_IIC.h对外发布函数接口和一些宏定义 , 函数 void IIC_confing_Pin( uint32 sda,uint32 scl, uint32 gpo);//设置 sda 和 scl 的引脚设置. 是主要调用的文件,它是基础。
#ifndef SIMU_IIC_H_
#define SIMU_IIC_H_ /*
*** Define some of the things ...*/
#define _NULL 0
#define _TRUE 1
#define I2C_ERROR _NULL //returns
#define I2C_FALSE _NULL
#define I2C_TRUE _TRUE
#define I2C_BUSY 3//3
#define I2C_DELAY_TM 5 //slot time (4.7us) /*
*** Define variables and structures ... */
typedef unsigned char uint8;
typedef unsigned int uint32; void I2c_Stop(void);
void I2c_NoAck(void);
void I2c_RecAck(void);
void I2c_Reset (void);
uint8 I2c_Start(void);
uint8 I2c_WaitACK(void);
uint8 I2c_RcvByte(void);
void I2c_SendByte(uint8 c);
uint8 Gpio_Pin_Red(uint32 pin);
void delay_ms(uint32 volatile number_of_ms);
void delay_us(uint32 volatile number_of_us);
void IIC_confing_Pin( uint32 sda,uint32 scl, uint32 gpo);//设置 sda 和 scl 的引脚设置. #endif /*SIMU_IIC_H_*/device_i2c.c 文件是给出的write和read实例文件。
#include "SIMU_IIC.h"
#include "usart.h" #define DEVICE_SLAVEADDR_W 0xA0//0x40
#define DEVICE_SLAVEADDR_R 0xA1
uint8_t busy;
uint8_t DEVICE_WriteByte (uint8_t addr,uint8_t *c,uint8_t len )
{
uint8_t i = ;
lock_busy = ;
i = I2c_Start(); if(I2C_BUSY == i )
{
printf(" \r\n I2C_BUSY \r\n");
goto DEVICE_WriteByte_FAIL; //return Fail;
}
else if (I2C_ERROR == i)
{
printf(" \r\n I2C_ERROR \r\n");
goto DEVICE_WriteByte_FAIL; //return Fail;
} I2c_SendByte(DEVICE_SLAVEADDR_W); //0x40 写
if(!I2c_WaitACK()) {
I2c_Stop();
printf(" \r\n 地址失败 :%02x !\r\n",DEVICE_SLAVEADDR_W);
goto DEVICE_WriteByte_FAIL; //return Fail;
}
I2c_SendByte(addr); //addr
if(!I2c_WaitACK()) {
I2c_Stop();
printf(" \r\n 寄存器地址错误 :%02x !\r\n",DEVICE_SLAVEADDR_W);
goto DEVICE_WriteByte_FAIL; //return Fail;
}
for(i=;i<len;i++){
I2c_SendByte(*c);
if(!I2c_WaitACK())
{
printf(" \r\n 写入数据失败 \r\n");
}
c++;
}
I2c_Stop();
busy = ;
return ;
DEVICE_WriteByte_FAIL:
I2c_Stop();
busy = ;
return ;
}
uint8 DEVICE_II_ReadByte (uint8_t addr,uint8_t * c,uint8_t len)
{
uint8 i;
busy = ;
if(!I2c_Start()) goto DEVICE_II_ReadByte_FAIL; //return Fail; I2c_SendByte (DEVICE_SLAVEADDR_W);
if(!I2c_WaitACK())
{
I2c_Stop();
goto DEVICE_II_ReadByte_FAIL; //return Fail;
}
I2c_SendByte(addr);
I2c_WaitACK();
I2c_Start();
I2c_SendByte(DEVICE_SLAVEADDR_R);
I2c_WaitACK();
for(i=;i<len;i++)
{
*c = I2c_RcvByte();
c++;
} I2c_NoAck();
I2c_Stop();
busy = ;
return ; DEVICE_II_ReadByte_FAIL:
busy = ;
return ;
}
《我的嵌入式开发》---- IIC 通信的更多相关文章
- ARM-linux嵌入式开发平台搭建1
初学嵌入式开发,由于是自学,走了很多弯路,现总结一下嵌入式ARM-LINUX开发环境搭建步骤: 1.安装linux系统,由于初学,我选择fedora 14.安装的具体步骤就不详细说了. 2.安装NFS ...
- linux交叉环境的搭建以及嵌入式开发概述
嵌入式开发概述 由嵌入式本身的特性所影响,嵌入式系统开发与通用系统的开发有很大的区别,嵌入式的开发分为系统总体开发,嵌入式硬件开发,嵌入式系统软件开发3大部分 在系统总体开发中,由于嵌入式系统与硬件依 ...
- C语言面试题(嵌入式开发方向,附答案及点评)
整理自C语言面试题(嵌入式开发方向,附答案及点评) 预处理器(Preprocessor) 1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SEC ...
- 与一线Linux嵌入式开发project师的对话
转:与一线Linux嵌入式开发project师的对话 陈project师一直做Linux的嵌入式开发.作为在开发一线的project师.他对非常多问题的看法可能更切合实际需求,于是,通过邮件.就嵌入式 ...
- 【嵌入式开发】写入开发板Linux系统-模型S3C6410
笔者 : 万境绝尘 转载请著名出处 最终拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧 ...
- 应聘linux/ARM嵌入式开发岗位
**************************************************************** 因为发在中华英才和智联招聘没有人采我所以我 在这里发布我的个人简历希望 ...
- 基于51单片机IIC通信的PCF8591学习笔记
引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...
- 【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410
作者 : 万境绝尘 转载请著名出处 终于拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧 ...
- 嵌入式开发 MCU
From: http://www.infoq.com/cn/articles/intelligent-embedded-os-Internet-of-things-and-robots 嵌入式开发是一 ...
- Node.js进阶篇-koa、钩子函数、websocket、嵌入式开发
代码地址如下:http://www.demodashi.com/demo/12932.html 一.简介 koa是由Express原班人马打造的,致力于成为一个更小.更富有表现力.更健壮的We ...
随机推荐
- json格式字符串用Uncaught SyntaxError: Unexpected token ' Uncaught SyntaxError: Unexpected number
Unexpected number(index)的错误用的json字符串如 var jsonStr = "{1:'北京note备注信息',2:'上海note备注信息',3:'广东note备注 ...
- C# 从配置文件中读取/写入信息
读取: var currMemberID = System.Configuration.ConfigurationManager.AppSettings["tolunaMemberID&qu ...
- 移动端click事件无反应或反应慢 touchend事件页面滑动时频繁触发
H5页面的点击事件click 无论在浏览器 iframe还是小程序里面 都会出现点击无反应或者反应慢的情况出现 所以决定用touchend事件来代替click 但是touchend事件触发比较灵敏 在 ...
- [Paper][Link note]
http://ieeexplore.ieee.org/document/6974670/
- maven源码打包
1.打包时附加外部Jar包 <!--编译+外部 Jar打包--> <plugin> <artifactId>maven-co ...
- [模板] 无旋Treap (C++ class)
注意!本帖不是算法介绍!只是贴代码(逃) //嫌stdlib的rand太慢,手打了一个 /* Author: hotwords */ typedef unsigned int tkey; class ...
- better-scroll
better-scroll会将默认事件阻止掉,如果自己写的部分需要有点击事件,需要在参数里加上click:true. 同时,在PC上或某些手机端,由于未成功将touchend事件move掉,点击事件会 ...
- callback回调函数的理解
callback采用的设计模式是:模板模式,他的设计理念是基于面向对象中的多态的. 我们的程序中走到某个地方他会出现不一样的动作的时候,我们在这儿就使用回调函数.我们利用的就是 多态的原理,我们传递不 ...
- KMP算法详细分解
1. 引言 给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题. Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的 ...
- Qt坑点汇总
1.场景:假如我们想在layout中的qlabel中设置一个图片 1.1 如果简单地使用border-image,我们可以做到,并且拖动界面时,label可以随布局正常变化,这里需要注意的是,修改ui ...