一周来都在尝试驱动DS1307,在用GPIO模拟I2C驱动不成功之后,尝试用硬件I2C来驱动,将I2C相关的代码复制到项目中,编译通过后但仍没有成功驱动DS1307,用逻辑分析仪抓取时序,发现单片机发出了地址信号,但没有应答信号,为了排除DS1307模块的问题,我将备用模块焊好排针测试,第一次似乎通过了I2C读写,但返回的数据全是零,复位再测试又不行了。" q8 F5 o1 F. m2 ~% G/ E# R
; F0 s( H2 b- e+ ^+ S7 T6 C% m
: j& ?) z7 P! _# P+ j/ Y F
% l) G% O8 {; u: K 通过分析时序图,发现单片机在发出地址之前还发出了11110000数据,不清楚这个字节的含义。进一步分析发现I2C通讯时高位在前、低位在后,而我从网上搜索到的DS1307驱动代码的模拟I2C通讯却是低位在前、高位在后,明显不符合通讯协议。下面是时序图:7 O% X) g6 P' a7 h7 ]
: Y3 B2 }( P& X/ f7 i
3 a$ \% m' ], R
2 E" X) X9 C. I 测试时单片机在不断地循环发出地址数据:
, _! w C/ w6 W" M
; B" i' p0 P1 y2 P% @, y5 V
; B }% q2 X' V5 u* e. f& D/ w( ~8 v, a( p- Q
+ X% {6 ?' G) W+ V+ {, i9 U4 O
/ A9 U8 Y" i0 z1 e7 K6 R1 R K. M9 y( N# h! I8 q$ S
硬件I2C对DS1307进行读写操作的代码如下,这个代码是参照范例写的,也不清楚是否会是代码有问题:
# k& v& ^& y& m- /******************************************************************************************
9 T* X: G: q5 F. H% S& j& P( h+ K$ X g - * 函数名称: DS1307_I2C_Read(): R( Z: t4 I6 g
- * 功能说明: 从DS1307地址addr开始获取size个字节的数据,获取的数据存储在全局变量DS_Buff中# {$ j) F% i- f$ @
- * 输 入: uint8_t addr 获取数据的开始地址
) v& d* C' `! K7 Q M! J( T - * uint8_t size 要获取的数据个数(1~8)& n" q' \2 V' Z% x! v
- * 输 出: ui08 0=RET_OK 成功从DS1307获取数据 >0=从DS1307获取数据过程中出现错误) U. J$ A# g6 O! e
- ******************************************************************************************/
; a: u4 f; A2 n. ` - uint8_t DS1307_I2C_Read(uint8_t addr,uint8_t size)
# |; R5 j. o9 X$ B - {: f2 D3 l7 | a3 p4 x9 u3 P+ L
- DS_Buff[0] = addr; //将要读取的起始地址发送给DS13073 d- \* [2 N. B [$ u) ~) t
- while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
5 a" j( j* H. E1 r% S) S. p - {7 B9 D' k1 F6 p) t
- if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)( V% Y/ X7 S4 L5 {7 q* E6 [0 g
- {
2 ] P* d, ]1 p - LCD_write_ASCII(0,3,1,(uint8_t *)"Read-Tr-ErrorA");
% w: ~) |1 U2 ~) R ?5 w - return 1;7 q5 y+ l$ B5 N; K4 q% i6 o
- }
# V" H- A l, c3 Q# [ - LCD_write_ASCII(0,4,1,(uint8_t *)"WriteAddr-ACK!");
9 u1 c8 C6 a, [; f) D; f2 A - }
- z2 |6 L. Y( Y' h8 j7 C) P - while (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)I2C_ADDRESS|1, (uint8_t *)DS_Buff, size, 10000) != HAL_OK)1 P& U; i+ {+ [; c2 n* t. x0 E
- {/ T, p {/ p" d% K. d4 k4 [# z: X
- if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
) R5 u# P4 x7 T9 q1 r - {
: [+ c$ e7 X3 E5 C! u$ n: | - LCD_write_ASCII(0,3,1,(uint8_t *)"Read_Tr_ErrorB");8 u" {2 F: T. V* t# y
- return 2;
: Q; [! T& \: | - }
( N* `9 L1 v# @7 O7 Q1 g# @ - }
1 L6 e3 v( [7 y. }3 S3 ^ J - return 0;
6 H( g( O: C. J9 c* O - }# w0 \9 x3 t2 H8 h# `3 r% S. b
) y$ T1 O, e7 @7 [. n- /******************************************************************************************
; \% e' m. u* I; t5 Q6 O - * 函数名称: DS1307_I2C_Write()% n- I1 x3 L: g) \7 h
- * 功能说明: 从DS1307地址addr开始写入size个字节的数据,数据存储在全局变量DS_Buff中' O% A! P: k$ l
- * 输 入: uint8_t addr 写入数据的开始地址% b; g6 Z% S+ h `7 |9 ^1 z8 O" V
- * uint8_t size 要写入的数据个数(1~8)9 x# M" N$ a N* X+ ~1 D4 z5 D
- * 输 出: ui08 0=RET_OK 成功写入数据 >0=从DS1307写入数据过程中出现错误
7 R( p& C/ u: o C1 n$ S - ******************************************************************************************/" {( D6 I7 {" L, h
- uint8_t DS1307_I2C_Write(uint8_t addr,uint8_t size)
; m& \7 @1 g6 ?* A0 ?; E8 a' W - {/ I, w) d1 \$ J/ l" t. ^; Q4 ~
- uint8_t i; b5 K3 @3 s/ W1 F$ W" L
- i = DS_Buff[0];
2 j! @! T* f* _& P" ~6 e - DS_Buff[0] = addr; //将要写入的起始地址发送给DS1307
4 j# V9 [/ ]5 d& o" X4 N8 y( C) ^5 } - while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, 1, 10000) != HAL_OK)
9 B" L/ m. L+ c6 {1 F/ { - {' t# b: x( m9 u- A' l/ a
- if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)6 B4 c& ~1 ~, J1 y& `( {/ C# H
- {3 t: `% R) g8 B
- LCD_write_ASCII(0,3,1,(uint8_t *)"Write_Tr_ErroA");/ o/ R8 K3 s" N' V7 y* I4 d9 _2 Q% [
- return 11;
) v$ p- x H4 o, q6 b1 d - }
n- y1 \3 Q( ]% B4 l1 J% T - }4 W, W2 X1 p3 {
- DS_Buff[0] = i;
( f- d$ r: z2 U - while (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)I2C_ADDRESS|0, (uint8_t *)DS_Buff, size, 10000) != HAL_OK)
0 {3 k# w9 }" h# M' L3 N" m - {
$ D& _+ A; R5 s; u - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)0 D: A" V5 p9 L0 ?! E( j
- {+ i7 ^1 B% `- \2 w: F9 W
- LCD_write_ASCII(0,3,1,(uint8_t *)"Write_Tr_ErroB");
7 P7 D V0 d. B. n, j - return 12;9 w+ s3 P* Y- }8 O% U% w* g" X- w# M
- }- J; O8 D2 q' V3 N2 e- u9 P( s
- }
) Y3 P4 c1 E5 B. |; U; U3 K - return 0;
" V M, R) B: q5 e - }& z2 t: D* w; D( R/ o) v& ?$ q( y: T
复制代码 $ ^' w* G' J7 d1 v
" M9 O% u7 ^+ _* h. n: N+ z" B
. U( t( a: H3 O7 r% B 不过我核对了DS1302的驱动程序,也是低位在前、高位在后通讯的,能够正常地读写,换句话说也许DS1302并不是标准的I2C。DS1307的I2C通讯时序尚未找到,但我这个模块是I2C总线除了DS1307外,还有一块AT24C32,而AT24C32是符合I2C通讯标准的,按理DS1307也应该同样符合。( F/ M: S) q0 T0 _4 O% G3 ~& U
下一步准备继续测试GPIO模拟I2C,一定要设法成功驱动这块DS1307。
$ y* Q. | Y. U0 S$ t x* k c* i! a
为了驱动DS1307模块已经花费了一周多的时间,原来还准备测试驱动智能小车的都没来得及,轮子及电机已经买好了,但电机驱动板尚未配齐,只有等以后再测试了:; Q* O4 E& M4 D9 I+ \2 S
$ z; M3 H c% U( j, {+ Y6 j0 k$ U
- Q8 e, b! R+ l
4 J+ K5 B/ }) T" \( j. b |
& r0 h- M9 Q2 B
现在正继续调试软件I2C,然后参照DS1307的数据手册来修改对DS1307的驱动。' s4 m6 {# {6 q+ I w