OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 20496|回复: 15

经过一个星期的努力,终于让STM32的硬件I2C跑起来了

[复制链接]

4

主题

13

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2015-1-12
在线时间
0 小时
发表于 2015-1-20 11:36:34 | 显示全部楼层 |阅读模式

下面是我用寄存器写的读写GT9系列IC的代码。在读数据上还不能连续读取,只能一个地址一个数据的读,请各位大哥指正。

//////////////////////////////////////////////////////i2c_hard.c

#include "i2c_hard.h"


void I2C_Init(void)
{
////////////////I2C GPIO重映像
 RCC->APB2ENR |= 1<<0;      //使能AFIO时钟
 AFIO->MAPR |= 1<<1;    //控制I2C1的SCL和SDA复用功能在GPIO端口的映像 SCL/PB8,SDA/PB9

////////////////I2C GPIO配置
 RCC->APB2ENR |= 1<<3;      //使能PORTB时钟
  
 GPIOB->CRH &= 0xFFFFFF00;    //I2C1:PB8->SCL, PB9->SDL 
 GPIOB->CRH |= 0x000000FF;    //复用开漏输出
 
 //GPIOB->CRL &= 0x00FFFFFF;    //I2C1:PB6->SCL, PB7->SDL 
 //GPIOB->CRL |= 0xFF000000;    //复用开漏输出

////////////////I2C 寄存器配置
  RCC->APB1ENR |= 1<<21;     //使能外设I2C1时钟

 RCC->APB1RSTR |= 1<<21;    //复位I2C1
 RCC->APB1RSTR &= ~(1<<21);  //复位结束I2C1
 
 I2C1->CR2 |= 36;                //000010:2MHz ... 100100:36MHz,其他禁用(此处为36MHZ) 

 I2C1->CCR |= 0<<15;    //I2C主模式  0:标准模式的I2C    1:快速模式的I2C
 I2C1->CCR |= 90<<0;            //时钟控制分频系数 = PCLK1/2/f(f为想得到的频率,此处PCLK1=36MHZ,f=200KHZ)

 I2C1->TRISE |= 37;    //最大允许SCL上升时间为1000ns,故TRISE[5:0]中必须写入(1000ns/(1000/36)ns = 36+1)

 I2C1->CR1 |= 1<<10;             //打开ACK应答,在接收到一个字节后返回一个应答
 I2C1->CR1 |= 1<<6;              //广播呼叫使能

 I2C1->OAR1 |= 0<<15;            //寻址模式   1 响应10位地址  0  响应7位地址
 I2C1->OAR1 |= 1<<14;            //必须始终由软件保持为 1
 I2C1->OAR1 |= INTERFACE_ADDR<<1;//设置接口地址的 7~1位(接口地址设为0X30)

 I2C1->CR2 |= 1<<9;              //事件中断使能
 I2C1->CR2 |= 1<<8;              //出错中断使能

 I2C1->CR1 |= 1<<0;              //开启I2C1       
}

void I2C_Start(void)      //I2C1产生起始条件

    I2C1->CR1 |= 1<<8;             
}
 
void I2C_Stop(void)      //I2C1产生停止条件

    I2C1->CR1 |= 1<<9;               
}

void I2C_End(void)                  //关闭I2C  

 I2C1->CR1 &= ~(1<<0);       
}

void I2C_Write_U8(u8 data)    //I2C1写一个字节

 I2C1->DR = data; 
}

u8 I2C_Read_U8(void)      //I2C1读一个字节
{
 while(!RXNE_STATUS);       //接收到数据标志位

 return I2C1->DR; 
}

u8 I2C_Write(u16 addr, u8* data, u16 length)
{
 u16 clear = 0;
 u8 addr_l=0, addr_h=0;
 u16 send_loop;

 addr_h = (u8)(addr>>8);
 addr_l = (u8)(addr&0x00FF);

 I2C_Start();

 while(!SB_STATUS);
 I2C_Write_U8(WRITE_ADDR);

 while(!ADDR_STATUS);
 clear = I2C1->SR1;
 clear = I2C1->SR2;
 I2C_Write_U8(addr_h);

 while(!BTF_STATUS);
 I2C_Write_U8(addr_l);

 for(send_loop=0;send_loop<length;send_loop++)
 {
  while(!BTF_STATUS);
  I2C_Write_U8(*data);
  data++;
 }

 I2C_Stop();

 return 0;
}

u8* I2C_Read(u16 addr, u8* data, u16 length)
{
 u16 clear = 0;

 u8 addr_l=0, addr_h=0;
 u16 send_loop;

 for(send_loop=0;send_loop<length;send_loop++)
 {
  addr_h = (u8)(addr>>8);
  addr_l = (u8)(addr&0x00FF);
 
  I2C_Start();
 
  while(!SB_STATUS);
  I2C_Write_U8(WRITE_ADDR);
 
  while(!ADDR_STATUS);
  clear = I2C1->SR2;
  I2C_Write_U8(addr_h);
 
  while(!BTF_STATUS);
  I2C_Write_U8(addr_l);
 
 
  I2C_Start();
  
  while(!SB_STATUS);
  I2C_Write_U8(READ_ADDR);
 
  while(!ADDR_STATUS);
  clear = I2C1->SR2; 

  while(!BTF_STATUS);
  clear = I2C1->SR1;

  *data = I2C_Read_U8();
  data++;
   
  addr++;

  I2C_Stop();
 } 

 return data;
}



//////////////////////////////////////////////////////i2c_hard.h

#ifndef __I2C_HARD_H
#define __I2C_HARD_H


#include "sys.h"
#include "led.h"
#include "delay.h"


#define WRITE_ADDR 0x28            //从设备(GT9)写数据地址
#define READ_ADDR 0x29         //从设备(GT9)读数据地址
#define INTERFACE_ADDR 0x30        //自身地址

#define SB_STATUS (I2C1->SR1 & 1<<0)  //起始位(主模式)
#define ADDR_STATUS (I2C1->SR1 & 1<<1)//地址已被发送(主模式)
#define BTF_STATUS (I2C1->SR1 & 1<<2)//字节发送结束
#define RXNE_STATUS (I2C1->SR1 & 1<<6)//数据寄存器非空(接收时)

void I2C_Init(void);

void I2C_Start(void);
void I2C_Stop(void);
void I2C_End(void);
void I2C_Write_U8(u8 data);
u8 I2C_Read_U8(void);

u8 I2C_Write(u16 addr, u8* data, u16 length);
u8* I2C_Read(u16 addr, u8* data, u16 length);
 
#endif









正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

13

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2015-1-12
在线时间
0 小时
 楼主| 发表于 2015-1-20 11:45:08 | 显示全部楼层
没有用中断和DMA,C文件中的一下两句忘记删除了: 
 I2C1->CR2 |= 1<<9;              //事件中断使能
 I2C1->CR2 |= 1<<8;              //出错中断使能

另外多谢好心人的帮忙
 @augustedward
 @login_FAE 
 @jermy_z 

O(∩_∩)O
回复 支持 反对

使用道具 举报

11

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2015-1-20
在线时间
0 小时
发表于 2015-1-20 12:06:58 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-1-20 23:40:35 | 显示全部楼层
不错,谢谢分享.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2015-1-21 07:52:28 | 显示全部楼层
谢谢分享!!!

不能连续读取,怎么破,这样不实际吧,一个地址一个地址来,太慢了,呵呵,我直接一页一页来,速度马上起来了,呵呵
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

4

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2015-1-19
在线时间
0 小时
发表于 2015-6-17 23:03:06 | 显示全部楼层
牛逼。学习了
回复 支持 反对

使用道具 举报

11

主题

52

帖子

0

精华

初级会员

Rank: 2

积分
89
金钱
89
注册时间
2015-7-6
在线时间
5 小时
发表于 2015-8-2 09:41:49 | 显示全部楼层
感谢分享!!
回复 支持 反对

使用道具 举报

11

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
111
金钱
111
注册时间
2015-7-21
在线时间
11 小时
发表于 2015-9-25 11:21:48 | 显示全部楼层
楼主你好,我用了一下你的代码,发现每次都在 while(!SB_STATUS)这里卡住,这是为什么呢?
回复 支持 反对

使用道具 举报

2

主题

11

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2015-3-31
在线时间
1 小时
发表于 2015-9-25 11:30:12 | 显示全部楼层
谢谢LZ,我们公司正在调GT911的电容屏,我们也是第一次调,LZ真是帮上了大忙,点赞,谢谢分享
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2015-9-25 13:33:11 | 显示全部楼层
谢谢分享,顶一个
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

0

主题

19

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
247
金钱
247
注册时间
2015-9-23
在线时间
39 小时
发表于 2015-9-27 10:13:10 | 显示全部楼层
回复【5楼】八度空间:
---------------------------------
贴出来看看
回复 支持 反对

使用道具 举报

7

主题

76

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
245
金钱
245
注册时间
2016-4-11
在线时间
54 小时
发表于 2016-12-19 18:04:29 | 显示全部楼层
请问,使用中断或DMA  没有崩溃,吗??
回复 支持 反对

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2018-9-25
在线时间
2 小时
发表于 2018-9-25 15:33:34 | 显示全部楼层
好东西啊,直接操作寄存了!
回复 支持 反对

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-25 17:48:39 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-25 17:50 编辑

有很多多年经验的码农从不用II2的硬件,理由是有bug, 实情是调不出来, 你比他们强多了如果整段代码在中断里做, 不用死等, 就满分了
回复 支持 反对

使用道具 举报

6

主题

305

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2876
金钱
2876
注册时间
2016-7-17
在线时间
404 小时
发表于 2018-9-25 19:02:42 | 显示全部楼层
看见寄存器代码真亲切,赞一下!
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2019-9-2
在线时间
0 小时
发表于 2019-9-2 16:01:34 | 显示全部楼层
用的是stm32的哪个系列啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-11 11:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表