一周来都在尝试驱动DS1307,在用GPIO模拟I2C驱动不成功之后,尝试用硬件I2C来驱动,将I2C相关的代码复制到项目中,编译通过后但仍没有成功驱动DS1307,用逻辑分析仪抓取时序,发现单片机发出了地址信号,但没有应答信号,为了排除DS1307模块的问题,我将备用模块焊好排针测试,第一次似乎通过了I2C读写,但返回的数据全是零,复位再测试又不行了。9 q7 Z5 K! e5 s% o8 j; w
- O' ^4 o) a0 K( M; q- ?6 W* ^ A- a/ |! x/ J p" B
7 e4 G* M1 f- Y$ B' v$ Z% Y 通过分析时序图,发现单片机在发出地址之前还发出了11110000数据,不清楚这个字节的含义。进一步分析发现I2C通讯时高位在前、低位在后,而我从网上搜索到的DS1307驱动代码的模拟I2C通讯却是低位在前、高位在后,明显不符合通讯协议。下面是时序图:
. _* j! Z1 g5 r4 `
1 I. D0 Q( p# X- Z
7 \# i; ^# e2 m1 w( [
+ O4 g* _. }* @0 T. X
测试时单片机在不断地循环发出地址数据:
' P1 _# p* j( X. f( {
6 u' J6 s- a1 ?# ?! n) S: e- e# f7 Q# J- a. p8 \8 t
/ q- [3 |. f0 F' j: Z
7 s" G) n2 d; G% p- }6 ]$ F7 p, {7 Q
' ~( E2 l! X" n, Z8 O, G
硬件I2C对DS1307进行读写操作的代码如下,这个代码是参照范例写的,也不清楚是否会是代码有问题:, P0 k( O- A$ `
- /****************************************************************************************** ! S: C$ p% |2 y
- * 函数名称: DS1307_I2C_Read(). |( A; g: p% F
- * 功能说明: 从DS1307地址addr开始获取size个字节的数据,获取的数据存储在全局变量DS_Buff中1 i l: T0 Q% [+ F
- * 输 入: uint8_t addr 获取数据的开始地址
9 s* f2 Q6 H* }6 B - * uint8_t size 要获取的数据个数(1~8)
8 A1 w- J6 V; k" o. u$ k - * 输 出: ui08 0=RET_OK 成功从DS1307获取数据 >0=从DS1307获取数据过程中出现错误/ A, C. j" l- A) J" K" \. d) {
- ******************************************************************************************/
/ P& r6 ~. l$ n1 v - uint8_t DS1307_I2C_Read(uint8_t addr,uint8_t size)
1 H6 Y1 S' Z! f2 [3 x- a, ^8 X, Z - {7 d1 T- b) z7 |
- DS_Buff[0] = addr; //将要读取的起始地址发送给DS1307
9 I) n: `6 f; \7 f5 z2 d - while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
" P/ x4 ?7 ~' W# T - {7 n& B7 W7 J5 h
- if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
; D4 p+ O+ q* B+ L, k: L- q - {$ r0 b( s# z& C- o. c; E9 o
- LCD_write_ASCII(0,3,1,(uint8_t *)"Read-Tr-ErrorA");
" ?2 u" O1 m Z. h - return 1;
8 k- I# q4 E' m, ^8 k; l - }4 J! W* ]# V0 u: h
- LCD_write_ASCII(0,4,1,(uint8_t *)"WriteAddr-ACK!");
2 n# R! h8 |' N$ _9 [# Y# | - }6 _0 Y; f' M; X- B7 g3 |6 n
- while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)I2C_ADDRESS|1, (uint8_t *)DS_Buff, size, 10000) != HAL_OK)
4 B! g0 Y1 R! e, h& L* q+ H - {
, ^" V( j0 Q. O3 ^ - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF), X* a7 y* P, `5 w
- {
; k/ n2 O' A/ X* U - LCD_write_ASCII(0,3,1,(uint8_t *)"Read_Tr_ErrorB");
0 [, M' H8 j* H+ R8 z# w - return 2;
4 t; E3 t" ?7 s1 d3 ]7 Q - }
/ ^" P* J3 Y9 |5 S - }
' k" o" A" }: @; f" T% n8 x0 Q V - return 0;: Q6 p# ^ G# w! z& B' T
- }
9 o2 T8 s4 z3 E: t0 N- M1 M - " Q" ? s' a) `( K8 B
- /******************************************************************************************
2 w. O" U9 w) [. [ - * 函数名称: DS1307_I2C_Write()
3 }4 _: X" Z2 r: d4 q5 G$ H2 d - * 功能说明: 从DS1307地址addr开始写入size个字节的数据,数据存储在全局变量DS_Buff中
) n# g, E# r4 M- c3 ~: ]/ Q - * 输 入: uint8_t addr 写入数据的开始地址% C/ ?0 ^$ d6 V1 K& Q$ R8 D
- * uint8_t size 要写入的数据个数(1~8)
* M! c/ z; y3 u) u0 l! m - * 输 出: ui08 0=RET_OK 成功写入数据 >0=从DS1307写入数据过程中出现错误) k* F( D' c% H g
- ******************************************************************************************/5 D5 @% a- L2 M0 F. c: F3 M" R
- uint8_t DS1307_I2C_Write(uint8_t addr,uint8_t size)* O9 L5 }2 f" l& G& B
- {
0 a9 S1 R- X% b% O, s4 v4 W - uint8_t i;4 h" h3 [3 g' A( L9 l+ Q
- i = DS_Buff[0];# h* f5 q2 a- M5 R/ y2 d5 |
- DS_Buff[0] = addr; //将要写入的起始地址发送给DS1307
9 L& U/ V. X7 A/ G - while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
3 H/ V; g; } X1 c9 v. R. M2 } - {
5 i- Z# {& {" y6 |: V# H - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
5 p2 O% \' t) \# \) k I$ O) P9 F5 c - {% m) `3 x# Y1 Z4 F1 c4 K
- LCD_write_ASCII(0,3,1,(uint8_t *)"Write_Tr_ErroA");
' d3 o* C& ^7 l9 W; c6 C - return 11;4 i7 H& |. U0 A% p( |) q
- }
+ ]; V- c* w; Z5 L - }
; @$ U f, ]8 C |* p1 j* [. }, z - DS_Buff[0] = i;
0 b/ K& f, x$ _ - while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, size, 10000) != HAL_OK)
1 X: x) b, I) p5 ?' S B3 w" i! d - {
K3 B$ N; i3 P9 ?, l - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
8 j5 Z, c; r# d" t0 U! u/ l7 i - {
6 T& ?3 g$ D- u W3 u0 z - LCD_write_ASCII(0,3,1,(uint8_t *)"Write_Tr_ErroB");
" a6 y' R! R. l% \# F: x - return 12;$ Q4 _& I5 N/ s. O; }
- }
: B U+ U) J1 Q4 k+ n: ]* ^* J) ~" s - }
' Z( c# k( M9 C5 n( W; Q! ^! h - return 0;
3 T4 v( _: k4 R - }
" C, s, n* h% _- Y2 X
复制代码 - M$ U% T& T6 I5 S
* i' |, g4 r( v; y; u
/ |( x* G, d0 h+ d
不过我核对了DS1302的驱动程序,也是低位在前、高位在后通讯的,能够正常地读写,换句话说也许DS1302并不是标准的I2C。DS1307的I2C通讯时序尚未找到,但我这个模块是I2C总线除了DS1307外,还有一块AT24C32,而AT24C32是符合I2C通讯标准的,按理DS1307也应该同样符合。8 `4 U" b4 Z" A
下一步准备继续测试GPIO模拟I2C,一定要设法成功驱动这块DS1307。
9 H' ] D) H! M
; {. _0 ?/ f3 T' Z3 n) v; Y! w 为了驱动DS1307模块已经花费了一周多的时间,原来还准备测试驱动智能小车的都没来得及,轮子及电机已经买好了,但电机驱动板尚未配齐,只有等以后再测试了:
# \( C* A1 P, u2 l. V/ \8 X0 A
4 b2 {- M$ D" j; `! {/ d3 r. Q Y2 d- d
4 l. C- y3 Y3 y: E/ ^
|
& b( ~, }, ^. N3 m
现在正继续调试软件I2C,然后参照DS1307的数据手册来修改对DS1307的驱动。! g8 P) I7 v: I) q4 z
4 `- }! U; y/ W, S