I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
3 t; O. s ^) j- T6 D8 Q1 z/ @2 U. {+ f- m8 ~ H+ G
这里使用的是G071RB开发板,已经自带有24C08A芯片,是一个8K的EEPROM芯片,使用I2C总线来控制这个芯片,写入数据。
- _) g/ y5 H1 ]" |1 u: a
" j1 ?1 m) e' v- d) R实验步骤
}6 z9 }2 L$ Q$ k) y, i1、CubeMx中芯片选择STM32G071RBTx,新建工程% v) @7 a0 @: a: R5 ~* o+ |' Q7 K/ u
& T. x( a; ^. D3 P8 [3 @6 |+ h
2、开启SWD调试、HSE
6 [& e. _& T' S; ]' {& C
0 K5 P4 f5 e; P6 z# m6 z& Y* ^# q! d7 o. ^0 W3 U0 U" \0 g3 k
p% x3 c: q% g1 ?1 F5 Y# V) z( B% _1 D \% {) u( j
0 v% M. e( V! d- s4 l* @3、开启USART1 ,设置波特率115200、8bit、None(无奇偶检验)、停止位18 a l6 e. F4 W9 Z% Z
1 s- K% L. O3 F5 c b4 _
4 B6 l2 ?# @& y4 q" r7 t! x. K5 X5 s1 {1 V. L: o& c) ?
4、 设置PB5为推挽输出模式,默认上拉,用于控制eeprom的WP引脚
- _0 r% p- D: P3 o5 Q, t# d- u: L4 B% u" B! e+ X
% ?) l3 |' E7 M2 m
9 A) s0 L* I) Q- B8 l" O0 ^5 N' T K
5、 选择PB7引脚,设置为I2C1_SDA,PB6设置为I2C_SCL,再激活I2C1,I2C Speed Moed选择:Standard Mode(标准模式),其他保持默认参数
, [) D2 f: w c3 a8 T) b4 q) p3 V2 o4 H7 z& N5 f; q2 R& W
( K" Z. ]; }7 q& O8 a7 {% `/ [. c
" c1 q$ a! e$ H8 X* b& Y6、设置时钟树,HCLK=64MHz6 o6 i: ]; y4 \8 ^' U
& x5 k a% n7 I8 `
. f" S9 s; A+ {" N" J
' P: |2 F4 \' x3 K1 U# e9 S9 @ 7、在工程管理里面,设置好参数,生成代码使用MDK打开。6 _5 v, D3 G( [% H/ N
, E5 m/ M) q, _: z/ e# _7 n
! m( C! a, W9 T. K) C! v' ]
& T8 y$ l2 L& f J; a1 L" h0 h' d
; K: v: s' Y& ?# Q3 A5 e% c, f
6 x* ?+ d! _+ U% |7 E代码部分
* y0 d+ t6 k/ ?" G1、在Debug选项卡中,Flash Download勾上“Reset and Run”1 t0 e6 D$ u0 ?+ l
' @. L4 `1 ?5 H2 \; u6 L: B2、添加printf打印代码,在usart.c文件添加如下代码
- w9 r% }, ?9 h
- C, I3 ^2 i' m- l- /* USER CODE BEGIN 0 */
2 w; {5 F" F/ P8 C h - #include <stdio.h>
8 w R' B' t! ?$ L" i; A* N - /* USER CODE BEGIN 0 */
( g0 p+ c1 C* x2 a+ Q# i - #ifdef __GNUC__
f+ e/ h/ x+ T+ T5 L+ h1 I - /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
# a, c4 n# c4 O5 D$ L& }& V - set to 'Yes') calls __io_putchar() */
+ ^$ e7 W. e3 E2 q+ H - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)& l8 u3 m1 Y, M6 Z+ c- U( c
- #else
4 Z: v* N& F0 \ - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)9 m/ e4 `) c5 e$ @- C/ d! w
- #endif /* __GNUC__ */
; a0 I" U2 Y, I( C. x8 Z; ~ J5 } - /**
9 Q+ \. @' e7 D& G, r - * @brief Retargets the C library printf function to the USART.
( |% s2 K6 {8 q( \8 E - * @param None. D% r5 x, w. l+ x) ?" k
- * @retval None
8 O1 r" u! t& B0 e. o$ v3 X# y - */3 ]% t0 \% f3 J# [' z3 z* o
- PUTCHAR_PROTOTYPE
4 \8 B& M$ B$ H: o! W5 T! M - {3 M: T4 d; q- p3 Z4 y! r# {
- /* Place your implementation of fputc here */
' \2 I. b3 H/ a, I* P, N/ a0 C" q - /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */2 o- Q' a! O* F
- HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);- g/ p+ W# }4 w8 ? A
- 2 E7 m P! y. W. o
- return ch;
( }$ X, B. Y: w( x - }
1 ^4 ]4 K" _3 F6 t: I' h - /* USER CODE END 0 */
复制代码
7 ?+ q1 _4 c' \* s, k, W/ h9 Y6 ^3、设置24C08A的地址
4 z0 ~- N# o1 F, u' d, W' i$ {; l: ]( l5 @& ]
这里用的是8K的芯片,所以有P1,P0位(),有4个块区域,每个区域有256字节。,这就是8K芯片。A0表示第一块256字节的设备地址,A2表示第二块256字节的设备地址,A4表示第三块256字节的设备地址,A6表示第四块256字节的设备地址
9 Y: I B# A7 y; R5 V) Y/ }. M: N# e% y# I) L
( |1 _$ {5 X: [2 S
5 V% I/ O/ n+ a( y( w在i2c.h文件中添加如下代码- /* USER CODE BEGIN Includes */
5 O, ^0 {% p! i6 f, u% \ - $ C0 H% f: v% G1 F: {
- #define ADDR_24LC08_WRITE 0XA0 //设备地址和写指令
c0 l0 v7 B1 k) |3 ~ - #define ADDR_24LC08_READ 0XA1 //设备地址和读指令( T. H6 P* A3 P, Z* E3 x. O3 @
- #define BufferSize 15& s% M/ n& C _
- % ]7 \& k" \! F$ ?1 R) \- U
- /* USER CODE END Includes */
复制代码 , @! D7 J$ t/ W7 g" [/ p( ^# W
4、在main.c文件中添加如下代码: f; G' Q5 I& A
# b. T' ?8 G/ Z6 P$ o, I5 p- /* USER CODE BEGIN Includes */7 c" }7 o; N6 P/ P
- #include <stdio.h>
# U: O& M. y5 o* v- h) b; {+ c! a6 } - #include <string.h>
, b; ~8 u2 T x - uint16_t i;
4 ^' t& L4 W, A1 |$ k# u+ e - /* USER CODE END Includes */
! X2 |( z. ^7 _) m* ]+ G
, Z; d. h a4 W+ ]/ M- int main(void)
* o. z6 F# s: h: w: S% _ - {; ]6 {7 q) |$ `, e Y5 R
- *$ K/ g3 w* l1 }
- *
* a/ f+ I1 Q7 X5 z) N3 \ - *
- c& V' d- Q! n - /* USER CODE BEGIN 2 */
' e( |1 l! R( U5 l: U. f - uint8_t writerbuff[BufferSize]="This is a test.";
" X" ^/ E: w5 T+ s& } - uint8_t readbuff[BufferSize];
& ]" p( K7 Z- v; C6 G6 n, e - HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET); //下拉引脚,激活eeprom芯片4 K2 ?7 P' }) q9 C4 z! c) D
- ! [* |/ t3 _9 Z+ S- u" U5 E
- if(HAL_I2C_Mem_Write(&hi2c1,ADDR_24LC08_WRITE,0,I2C_MEMADD_SIZE_8BIT,writerbuff,BufferSize,0x10)==HAL_OK)
5 O( z' J9 P5 Y5 T2 |5 V& I' J1 P - printf("Write succeeded.\r\n");/ E8 g* z7 |) A
- else' x) C; E0 H# F0 D- U$ G
- printf("Write failed.\r\n");% K8 n I6 P& V: @5 T3 f) K; _. ]
- HAL_Delay(5); //等待芯片写周期完成
% R+ E2 I4 i8 Z/ P1 q! N - HAL_I2C_Mem_Read(&hi2c1,ADDR_24LC08_READ,0,I2C_MEMADD_SIZE_8BIT,readbuff,BufferSize,0x10);
) m1 Z+ i) {# Q. ~1 `( G - printf("The data in the chip is as follows:\r\n");0 O, f/ Y# N# l% T5 t: h7 R0 f$ y+ K
- for(i=0;i<BufferSize;i++) //读取的数据通过串口打印出来
& i; _. A( h7 Y$ q: d - { K% ^: E# }# q, ]% C6 x
- printf("%c",readbuff<i>);
1 l5 ^! ^9 I& N; k7 G - }
- u& u0 D/ R/ z9 H. n# ~1 h! G - if(memcmp(writerbuff,readbuff,BufferSize)==0) //对比写入数据与读取数据是否一致
$ L7 h+ f+ D/ b- j E - printf("\r\nVerification succeeded.\r\n");6 F2 a$ i. B0 ~$ A
- else% ]+ l* T: H9 T A
- printf("\r\nVerification failed.\r\n");
+ b3 q+ E4 N! S# K8 g" ~2 Y - *' V7 a Z- a, `. d, Y; d
- *0 W0 I- G. W9 [; w
- ** h6 a, t K0 j- A% Q- B2 M! Y
- }</i>
复制代码
: q9 B8 y, }) P' _1 c( V; s6 w/ [5、编译好固件后,烧录进去芯片。串口输出如下5 r: L" J+ h/ G* {$ B8 w5 T3 @/ P
: u/ F' u8 p }; i# W% i( X4 d4 n0 N' v5 A9 E! Q6 F: `
|