打印

STM32 I2C 封装库(查询方式+29楼中断方式+32楼DMA方式)

[复制链接]
37586|88
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lut1lut|  楼主 | 2008-12-26 15:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
中断方式正在调试,即刻出炉;DMA方式有待实现。

这里先暂时放出STM32作为主设备的读/写函数。只需要指出
(1)端口(I2C1 or I2C2)
(2)从设备地址
(3)发送数据指针/或者接收空间指针
(4)数据长度
即可。

查询方式有超时控制,返回错误代码。

另外,基于大家都熟悉并且痛恨的FWlib中I2C-E2PROM的例子,改过来的,大家看起来会熟悉些。

压缩包中除了项目文件,还有一个说明文档doc,请参阅。

欢迎大家排砖~~~
沙发
lut1lut|  楼主 | 2008-12-26 15:49 | 只看该作者

忘了上传压缩包

代码已经修改,请大家更新后使用
相关链接:https://bbs.21ic.com/upfiles/img/20093/2009318145734823.zip

使用特权

评论回复
板凳
mei5150| | 2008-12-26 16:41 | 只看该作者

以ZGGCD的名义

感谢楼主!

使用特权

评论回复
地板
香水城| | 2008-12-26 16:49 | 只看该作者

很多人都说STM32的I2C不好用,我们特意做了这个函数库

把有关I2C模块和I2C协议的细节包在了函数内部,使用户不用了解I2C模块和I2C协议的细节即可使用I2C。

请大家试用并提出意见。

使用特权

评论回复
5
starm| | 2008-12-26 17:05 | 只看该作者

支持一下

比以前的调用方式, 简洁了许多.

使用特权

评论回复
6
llyygg1971| | 2008-12-29 08:29 | 只看该作者

很好,支持

最好不用 Systick,很多RTOS会用到它

使用特权

评论回复
7
winloop| | 2008-12-29 09:12 | 只看该作者

“请大家试用并提出意见”

香主指的是哪个?指楼主发布的库?

使用特权

评论回复
8
lut1lut|  楼主 | 2008-12-29 11:18 | 只看该作者

可以变通对Systick的用法

谢谢llyygg1971的宝贵意见:

对于使用操作系统的环境,如果Systick已经被用来作为内核时钟,那么仍然可以基于这个已经被使用的systick作为I2C操作的超时。

只需变通一下即可:显然这个Systick会一直被使能并且运行,是一个"free running"的自减计数器。假设操作系统内核的每个时钟节拍为20ns,那么Systick就每20ns产生一次中断(当然这需要设置合适的Systick时钟源和重装载值),在这个中断里可以自加时钟节拍这个变量值。

在等待某个事件之前,读取当前时钟节拍值为ValuePre,假设这次等待的超时定义X(ns),那么当时钟节拍值变为ValuePre+X(ns)/20ns,表示该等待超时。  可以表达为 while(!(event||(当前节拍值==ValueP + X/20) )

很多情况大家帮我想到,我可以最后修改的时候都融合进去,谢谢。但是,如果最终没有cover到某些情况,还是希望大家自己能够变通~~~

使用特权

评论回复
9
wakaoo| | 2008-12-29 17:58 | 只看该作者

请问LUT1LUT老师

我用的EK STM32 学习板,对应LUT1LUT老师以前修改的I2CEE.C可以写读E2PROM,但是用这个程序就会卡在while(!I2C_OT)里面,请问这个是哪里出问题了?我是这样设置 I2C_Comm_Init(I2C1, 300000, 0xA0);的

使用特权

评论回复
10
lut1lut|  楼主 | 2008-12-30 09:33 | 只看该作者

这里是等待一段时间

可以参看代码里的注释。单独while(!I2C_OT),都是在等待一段时间过去,比如等待5us(以保证I2C规范中的bus free time),或者是等待I2C总线上10个时钟脉冲的时间。

这相当于用Systick来定时而已,不会死在这里的啊。我这里才用你的初始化跑了一下。

这里不要单步执行试试。

使用特权

评论回复
11
wakaoo| | 2008-12-30 10:23 | 只看该作者

再请问下lut1lut老师

会不会是固件库的问题?我用的是100脚的芯片,而你用的是144脚的芯片。然后固件库也是144脚的。我还是会卡在while(!I2C_OT)哪里,就不走了。然后static u32 one_us_unit=0;
static u32 i2c_10clk_us=0;我也没有改他。就把MAIN程序里面的用到GPIOF的语句删掉了。然后还有WHILE(1)里面的也删了。然后I2C_Comm_Init(I2C1, 300000, 0xA0);这个设置也没改。 麻烦老师看看,谢谢了

使用特权

评论回复
12
lut1lut|  楼主 | 2008-12-30 10:54 | 只看该作者

stm3210x_it.c用的是项目中的么

void SysTickHandler(void)
{
  systick_isr();
}
分析一下:死在while(!I2C_OT),是因为I2C_OT没有置位-->该变量只在<i2c_comm.c>开头处的
void systick_isr()
{
  I2C_OT = TRUE;
}被置位。而这个函数是由SYSTICK的中断函数调用的。

如果I2C_OT这个变量没有置位,两个原因:
1.systick没有跑起来 --〉貌似不可能
2.systick的中断到了,但是没有调用systick_isr()咯。

另外,固件库跟多少pin脚没有关系,都是公用一个库

(拜托,不要叫我老师,大家一起学习探讨STM32而已)

使用特权

评论回复
13
wakaoo| | 2008-12-30 12:27 | 只看该作者

谢谢lut1lut

谢谢lut1lut。 是中断里面的问题。我没注意到。麻烦你了。

使用特权

评论回复
14
lut1lut|  楼主 | 2008-12-30 17:45 | 只看该作者

欢迎大家拍砖

最后会汇总各种意见,再做修改。

现在收集到的一个就是:做超时的Systick用另外一种方式,兼顾OS会用它作为系统节拍的情况。

如果广大21ic网友不满意可以提出具体意见,谢谢。

使用特权

评论回复
15
hero.feng| | 2009-1-2 19:57 | 只看该作者

好,收下了!

好,收下了!

使用特权

评论回复
16
hjiongh| | 2009-1-5 14:27 | 只看该作者

我用了这个例程读写24c16 失败了~~~

完全照抄,然后:

I2C_Comm_Init(I2C1, 400000, 0x0);

  I2C_Comm_MasterWrite(I2C1, 0xa0, 5, Tx1_Buffer, 2);
  I2C_Comm_MasterRead(I2C1, 0xa0, 5, Rx1_Buffer, 2);

但是Rx1_Buffer 里面不是/* STM32F10x I2C Firmware  


哪里出问题了?

我是101的片子,外接了一个24c16,用的i2c1

使用特权

评论回复
17
香水城| | 2009-1-5 14:35 | 只看该作者

请先用较低的速度试通,保证硬件连接没有问题,再提高速

否则很多东西混合在一起,很难诊断问题在哪里。

“Rx1_Buffer 里面不是/* STM32F10x I2C Firmware ”——这句话什么意思?

使用特权

评论回复
18
lut1lut|  楼主 | 2009-1-5 14:36 | 只看该作者

你看函数返回错误代码是什么?

typedef enum i2c_result
{
  NO_ERR  = 0,  
  TIMEOUT = 1,
  BUS_BUSY = 2,
  SEND_START_ERR = 3,
  ADDR_MATCH_ERR = 4,
  ADDR_HEADER_MATCH_ERR = 5,
  DATA_TIMEOUT = 6,
  WAIT_COMM = 7,
  STOP_TIMEOUT = 8,
  WRITE_FAILURE = 9,

}I2C_Result;

使用特权

评论回复
19
hjiongh| | 2009-1-5 14:46 | 只看该作者

查了一下硬件,原来eeprom写保护了

写保护了,怪不得。现在可以读写了

我现在暂时去掉了函数返回错误代码,直接看read的buffer的。

这个例程有个问题不好,楼上有人说过的,用的是SysTick. 我SysTick用于其它定时的。 而且都是ms级的。最好能有一个其它超时的来给i2c1

使用特权

评论回复
20
hjiongh| | 2009-1-5 14:54 | 只看该作者

搂主对于14楼的说法有结果了吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

483

帖子

3

粉丝