STM32F103 Slave I2C配置

发布者:咖啡小熊最新更新时间:2019-04-08 来源: eefocus关键字:STM32F103  Slave  I2C配置 手机看文章 扫描二维码
随时随地手机看文章

才接触STM32开发,由于项目需求需要,需要linux系统与STM32通过I2C进行通讯,网上合适资料有限,花了不少时间,所以记录在此。


描述:Linux发送数据后,每隔10ms轮询stm32(应该做中断触发的,但由于硬件接口限制),只读一个字节判断是否有数据,如果有则读相应长度的内容。


自定义缓冲区格式:首字节为长度信息,后面是内容信息,如

uint8_t I2C_Buffer_Rx[128];//0:len  1...=>data

(1)I2C Slave初始化


void IIC_Init(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  I2C_InitTypeDef I2C_InitStructure;

 

  RCC_APB2PeriphClockCmd  (RCC_APB2Periph_GPIOB , ENABLE);

 

 

   /* Configure I2C2 pins: SCL and SDA */ 

   GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_10|GPIO_Pin_11; //10:SCL 11:SDA

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//Out_PP;

   GPIO_Init(GPIOB, &GPIO_InitStructure);   

   RCC_APB1PeriphClockCmd  (RCC_APB1Periph_I2C2, ENABLE); 

   I2C_DeInit(I2C2);

   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

   I2C_InitStructure.I2C_OwnAddress1 = 0x10<<1;//temp addr

   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

   I2C_InitStructure.I2C_ClockSpeed = 400000;

   I2C_Init(I2C2, &I2C_InitStructure);

   I2C_ITConfig(I2C2, I2C_IT_EVT|I2C_IT_BUF, ENABLE);

   I2C_Cmd(I2C2,ENABLE);

}

(2)I2C中断配置

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

 

  NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

 

}


上述两条是基本操作,仔细看参数是没啥问题,最麻烦的是I2C状态,使用官方的问题很大,例如:

#define  I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED       ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */


而实还有0x20402的情况,类似情况太多了,经常冒出一个新状态,并且接收和停止可能合在一起。我开始使用case语句来判断状态的,待状态测试稳定后使用if来进行Bit位判断,目前比较稳定。见I2C中断处理。


(3)I2C中断处理


此地方核心是I2C状态处理,收发的数据格式类似串口操作,代码如下:


uint8_t I2C_Buffer_Rx[128];//0:len  1...=>data

static uint8_t I2C_Buffer_Tx[128];//0:len  1...=>data

void I2C2_EV_IRQHandler(void)

{

     uint32_t  I2CFlagStatus;

     static uint8_t num = 0;

 

     I2CFlagStatus = I2C_GetLastEvent(I2C2);  // =>  (SR2<<16|SR1)

 

     if ((I2CFlagStatus & 0x02) != 0){ //bit1:addr matched

           if(I2CFlagStatus & 0x80) //bit7 Data register empty (transmitters)

            {//read            

               num = 0;  

               I2C_SendData(I2C2, I2C_Buffer_Tx[num]);

           }else{ 

               num = 1;  

              I2C_Buffer_Tx[0] = 0;

              I2C_Buffer_Rx[0] = 0;

             }

     }else if((I2CFlagStatus & 0x80) != 0){ // bit7  TxE  -Data register empty (transmitters)

           if((I2CFlagStatus & 0x04)==0){ //bit2  BTF (Byte transfer finished)

                num++;

                I2C_SendData(I2C2, I2C_Buffer_Tx[num]); //printf("I2C status:0x%xrn", I2CFlagStatus);

           }

     }else if((I2CFlagStatus & 0x40)&&(I2CFlagStatus & 0x10)){  //bit6(RxNE) +  bit4(STOPF) 

           I2C_Buffer_Rx[num] = I2C_ReceiveData(I2C2);    //g_debug_count1++;

            num++;   

           I2C_Buffer_Rx[0] = num-1;

           I2C2->CR1 |= 0x1000;//CR1_PEC_Set;

     }else if((I2CFlagStatus & 0x40) != 0){ //bit6  RxNE    -Data register not empty (receivers))

           I2C_Buffer_Rx[num] = I2C_ReceiveData(I2C2);   

           num++;     

     }else if((I2CFlagStatus & 0x10) != 0){ //bit4  STOPF -Stop detection (slave mode)

           I2C_Buffer_Rx[0] = num-1;

           I2C2->CR1 |= 0x1000;//CR1_PEC_Set;

     }else{

         printf("I2C error status:0x%xrn", I2CFlagStatus);

     }

 

I2C2->SR1=0;

I2C2->SR2=0;

}


(4)数据接收处理

我传输的数据长度是7到128字节之间。


void Recive_RXD_Deal(void)

{//I2C_Buffer_Rx  0:len  1->data

u8 i,len;

  

       len = I2C_Buffer_Rx[0];

if(len)

{

/*printf("i2c recv len:%d:",len);

for(i=1; i<=len; i++)

printf(" %x ",I2C_Buffer_Rx[i]);

printf("endrn");*/

    

                  if(len < 7) return;

       

     if( len != (I2C_Buffer_Rx[3]+1)) return;    

             

     if(I2C_Buffer_Rx[len-1] == (unsigned char )(Cheak_Sum(len-4, I2C_Buffer_Rx+3) &0xff))

UART2RXBuffer_Checked = &I2C_Buffer_Rx[1];

RXD_Deal_PROCESS();

}else{

    printf("checksum error data[%d]=> ",len);

    for(i=0; i<=len; i++) printf(" 0x%02x",I2C_Buffer_Rx[i]);

    printf("endn");

}

I2C_Buffer_Rx[0]=0;

}

}



(5)数据发送接口:



void Raspberry_Send_Datas(unsigned char  *data,uint16_t length)

{

  uint8 i;  

 

    // printf("send data len[%d]:",length);  

      for(i=0; i

   I2C_Buffer_Tx[i+1]=*(data+i);

   //  printf("%x ",*(data+i));

      }

// printf("endrn");

 

         I2C_Buffer_Tx[0] = length+1;  

}



应该就上面这些了。

关键字:STM32F103  Slave  I2C配置 引用地址:STM32F103 Slave I2C配置

上一篇:STM32F103RC硬件I2C从入坑到出坑
下一篇:Dht11与Ds18b20温度传感器使用

推荐阅读最新更新时间:2024-03-16 16:26

STM32f103C8T6 bootloader设计
使用的是STM32f103C8T6:64Kflash,在应用程序中通过CAN把接受到的bin写到外置 flash的指定地址处。在bootloader中判断一个单独的标志位看程序是否需要升级,如果需要升级,则复制外置flash处的内容到STM32的内置flash的指定地址处。 如: bootloader地址:0x08000000UL 大小:10K——0x2800——STM32的内置flash 应用程序地址:0x08002800UL 大小:45K——0xB400——STM32的内置flash 升级信息表:0x720000UL 大小:8K——0x2000——外置flash 升级的bin文件地址:0x080124
[单片机]
STM32F103使用内部Flash保存参数
在我们应用开发时,经常会有一些程序运行参数需要保存,如一些修正系数。这些数据的特点是:数量少而且不需要经常修改,但又不能定义为常量,因为每台设备可能不一样而且在以后还有修改的可能。将这类数据存在指定的位置,需要修改时直接修改存储位置的数值,需要使用时则直接读取,会是一种方便的做法。考虑到这些数据量比较少,使用专门的存储单元既不经济,也没有必要,而STM32F103内部的Flash容量较大,而且ST的库函数中还提供了基本的Flash操作函数,实现起来也比较方便。 以大容量产品STM32F103VE为例,其Flash容量达到512K,可以将其中一部分用作数据存储。如下是大容量的Flash组织模式: 根据上面的Fl
[单片机]
<font color='red'>STM32F103</font>使用内部Flash保存参数
STM32F103的简易串口驱动(查询方式)
对于各个模块的学习,开始通常是只使用最简单的功能。这里将给出一个STM32F103的最基本的串口收、发驱动。要使用串口,就需要对串口的波特率、数据格式等进行设置。这里给出的例子是使用的USART1,它的时钟是连接在APB2上的,在计算波特率时应该使用APB2的输出时钟。另外,使用查询方式的话,还需要禁止掉串口的相关中断,以防止程序跑飞。由于STM32F103的串口引脚是跟普通IO口复用的,所以在使用之前,一定要记得初始化对应的IO口,选择为相应的第二功能,否则串口将无法正常工作。 首先对照STM32F103的数据手册,将相关寄存器的定义写好,放在USART.h头文件中。然后增加对串口的初始化、串口读写操作的函数即可。本测试程序功能很
[单片机]
基于STM32F103——AS608指纹模块+串口打印
最近用STM32F103做一个智能门锁小玩意,其中用到指纹模块,我这里也单独的写一下笔记,不过我只是了解了基本的,就是我做门禁卡要用到的几个东西,其它还没了解。为了方便,做一下记录。我这里没有用到按键和显示屏,所以还是串口输出输入来控制了 哈哈哈哈 一: 基本介绍 这里就写一下我这次用到的而且觉得是重点的东西吧 毕竟手册还是内容很多的 AS608引脚描述 这里就留意前6个 其中WAK这个引脚 是可以检测手指是否按下的 当有手指按下 WAK引脚是输出高电平 没有手指则维持低电平 AS608模块地址 默认是 0XFFFFFFFF(共4个字节) 我这里就不改了,按默认的了。修改的话请看手册 AS608波特率 默认是576
[单片机]
基于<font color='red'>STM32F103</font>——AS608指纹模块+串口打印
STM32F103:SWJ调试端口设置成普通I/O口
一、SWJ调试端口 STM32有两种程序调试接口(程序烧写口),具体如下: SWD调试接口: PA13、PA14共两个引脚。 JTAG调试接口: PA13、PA14、PA15、PB3、PB4共五个引脚。 单片机启动后,初始状态这五个引脚就默认是调试接口。 而实际使用中,一般只使用 SWCLK、SWDIO这两个引脚用做SW调试接口。 其余的三个引脚可以空出来,重新定义为普通I/O来使用。 如果需要将它们用作普通IO口,需要进行引脚复用,禁止调试功能。 二、SWJ调试端口设置成普通I/O口步骤 1. 配置复用时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE ); //配
[单片机]
<font color='red'>STM32F103</font>:SWJ调试端口设置成普通I/O口
基于STM32F103VE的智能信箱系统的设计与实现
引言 为了解决传统信箱容易发生的锁孔堵塞、钥匙丢失、信件丢失、浪费空间、垃圾广告等问题,保护信件的安全、有效,我们设计了一个智能信箱系统。它采用封闭式管理和细化空间、动态分配的存储理念,增加了安全性,提高了用户数量。它还具有身份验证、来信提示、网络查询等功能,可以广泛应用于小区、学校、医院、企业等。 一、 整体构架 智能信箱的系统构架主要有两部分,即控制系统与机械设备。控制系统用于保存和管理用户与信件的信息,下达“存”或“取”的命令给机械设备,它包括主控芯片模块、存储器、触摸屏、网络接口、实时时钟、电磁继电器、步进电机驱动器等;机械设备则负责执行控制系统下达的命令,完成信件的存取过程,它包括带步进电机的线性十字滑轨以及用于存
[单片机]
基于<font color='red'>STM32F103</font>VE的智能信箱系统的设计与实现
STM32f103 看门狗使用
//看门狗使用需要计算超时时间 // IAR 7.1 #ifndef __STM32_WDG_H__ #include stm32f10x.h #define LSI_FREQ 40000 void stm32_wdg_init(void); void stm32_wdg_enable(void); void stm32_wdg_feed(void); #endif #include stm32_wdg.h #include stm32f10x_iwdg.h void stm32_wdg_init(void) { /*Enables write access to IWDG_PR and IWDG_RLR regist
[单片机]
STM32F103启动文件注释
1、启动文件作用: (1) 初始化堆栈指针 (2)初始化PC指针指向复位程序 (3)初始化中断向量表 (4)配置系统时钟(3.0版本之前,进入main函数后,首先配置系统时钟,但是3.5.0版本固件库配置了时钟,所以就不用配置 了,因此在用固件库的时候,看一下注释,如果已经配置,就不用自己配置了。) (5)调用C库函数_main,进入C语言的世界。 ;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** ;* File Name : startup_stm32f10x_hd.s
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved