项目简介
) h7 M, p$ @$ s6 m9 A' d 利用CubMX生成基于32单片机的HAl库工程,然后编写程序在proteus上仿真验证。本项目最适合没有开发板的同学学习,零成本利用仿真软件率先入门STM32单片机。这是第四部分针对EEPROM 24C02的一个实例,IIC通信是一种比较典型的串行通信方式,在很多情况下都会有所使用,了解并熟悉IIC通信就显得十分重要。本项目之所以使用模拟IIC,而没有使用STM32单片机内置的硬件IIC,主要由于Half库里IIC的坑太多了,自己一开始也是想通过HAL库来开发,但是始终不成功,也有可能仿真软件也有些坑,如果有能够做出来的大佬,也欢迎评论区或私聊我交流,不过在实物32单片机开发板上网上好像验证过可用,但是手上暂时缺开发板,针对硬件IIC这一块的内容,以后有时间会完善。& K9 o2 ?1 Z4 }( H* z; T
" M7 E' q3 K r6 f3 \
硬件模块9 M$ `; w0 A( B2 T& |
STM32F103R4
9 N" [1 `% w7 w8 I; r/ N; E0 j
- s* b7 ]" H, l7 }2 c5 ^ 24C02' r( r* Z+ [, G; C
: E. ^. i4 ?7 b9 C7 w1 f" F 串口模块; Y. J3 S8 Y# I. o m
( W$ C- ?+ x0 x* J Y; x9 F! z
软件工具* M" L1 @8 ^: J4 X1 J9 _4 o
CubMX
% T X/ ?; _7 B$ g# |7 P E4 E) |6 I# O. @* c: Q! ^& k) _) m
Proteus
$ ~; q) T( G8 y9 z1 @* X2 ]- S4 i
KEIL# ?; I( s7 \1 ]! [# [
& W/ M5 P: Q4 v0 c( ^( ~. ^
电路连接图
+ H7 X; s5 O7 O! A4 J/ l! ~, K; }1 ^
# q, t5 J }5 d, ^, q3 D
* a& }; r& y, C5 e& {0 A
7 \7 [% u" ?) t/ S
8 L! x+ ~4 ~$ i4 z, [
7 M2 L1 z2 Z9 c9 w% d工作流程
3 r7 C2 v9 h( |' M8 w5 S 首先创建一个CubMX工程,如果是配置硬件IIC很容易,只要简单选择一下就可以了
& b1 T4 [+ k* a( M0 ~* f/ G J
5 J: @- e l; u0 ]- Z/ D
- ^# ~5 c; `) O \9 W, i( J! W) K/ e _4 b% Q
默认是标准模式,速度是100kHz,可以选择高速模式400kHz,其余可以保持默认,当然这是硬件IIC的配置方法,咱们用的是模拟IIC,相应的引脚设置在后面生成的Keil工程里编写相应程序即可。
+ q8 v" ^0 R. J* l* j8 u7 Y; g7 j6 W) O3 d5 e2 m
0 o0 ^$ R' j2 m. m) E9 F0 D& { i+ d# x+ ]* u
其余也是保持默认即可
: p9 z, u$ y: c0 O: C& v! a$ ~
& t. z4 E/ r- {. |2 P
6 E+ L ?9 K5 p8 g% ~
r1 U: j# G) v2 v: {5 Z
) X. V( W; p2 v& G- v2 V" v) _; N. m; X6 w+ m+ x, c* Z) S
之后,在生成的KEIL工程中编写相应的程序,这部分在后面会列出。
. q6 g# X# N+ I; y8 E/ M4 ]; _- I. [7 }! N
然后就是验证了。将提前设置的一组数据写入进24C02中,然后从24C02中读取出来,并用串口打印,提前设置的数据是{1,2,3,4,5,6,7,0} ,串口打印出的数据如下:
) ]- `) }( _) U# E6 I
$ u7 a0 v0 o7 e
& ^+ A3 f4 X; L5 h1 R. b& T* d. A/ N% _ } f% s
% w, j5 w4 \' ~* U+ |) e1 {程序代码4 q# p/ d1 g! ^8 u
main.c/ [7 a, n3 h5 p0 L; {2 s/ U
: q5 g4 O( X0 x3 d! T/ m4 A
- uint8_t WriteBuffer[2*BufferSize] = {1,2,3,4,5,6,7,0}; //需要写的数据在WriteBuffer当中
0 o5 l5 [4 ]( M6 I- Q) d - uint8_t ReadBuffer[2*BufferSize]={0}; //读出来的数据放进ReadBuffer当中+ L* K1 l, z* r. `* }2 T
- uint8_t i;
4 m$ G0 V- R% b6 {1 i - uint8_t data_addr = 0x01;% O/ [" p) g" Y# K; |# H
- /* USER CODE END 0 */ w2 u; V/ m/ ^3 q2 W2 E
" L" t* H; b/ z( B- //重定向printf()到串口发送和接收,方便应用3 J+ ^! F% j! A& A/ R
- int fputc(int ch, FILE *f){% H( }# f! S6 X
- uint8_t temp[1] = {ch};
5 I, h# ~8 o+ ?% E7 _ - HAL_UART_Transmit(&huart1, temp, 1, 0xffff);! b' R/ z9 L" M. ] m( o$ h. H
- return ch;
3 Q4 A' a$ S j" ]/ x - }, e7 j3 `! c) X# B, [
- //重定向scanf()函数和getchar()函数,方便应用
4 w o% [0 G* N( ^( e - int fgetc(FILE * f)2 T$ y4 R- l0 h8 }/ p, I# i5 j, @
- {& j& s( U' Y$ Q* j
- uint8_t ch = 0;
6 D1 Z, T; i% `) H0 r - HAL_UART_Receive(&huart1,&ch, 1, 0xffff);6 E j4 D0 u6 [+ g5 A
- return ch;
5 ?' `1 v2 w5 n# T; W3 T - }
6 ^; k4 [* d! [, ?2 k
* V$ i2 U# {- B: z3 N- Y3 q- /**2 N; [+ q7 E- p3 O: M
- * @brief The application entry point., y2 D1 w; A( H
- * @retval int
6 \8 J1 J) _2 @ - */8 T/ ^0 t) z( A1 O; a! @
- int main(void)
9 r' m6 V) N3 T' D7 L; o - {5 b$ M# ]* r- ^5 \
- /* MCU Configuration--------------------------------------------------------*/
: o! s, @+ N5 `/ j% U% _) a
+ H% ~9 T. S u$ d7 O, d- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
; A2 b1 Y! J, \! l* v$ Q2 g3 U - HAL_Init();
/ M. P" U! t& N# v7 H0 I& L5 S
( v D2 A! |* h# D- /* USER CODE BEGIN Init */
! J: W9 |0 E+ `8 { - 5 v) t' E5 A6 q# K6 `4 I" J1 i: p
- /* USER CODE END Init */
3 v- U( Y5 s! s" T5 Q - 0 d1 V7 S6 _% D: V7 D1 W7 h; E) y
- /* Configure the system clock */
7 u+ P! m$ J5 _# P5 R - SystemClock_Config();
' f* P3 m9 `: ]# I
8 O* X! h! O2 K4 p u9 L- w- /* USER CODE BEGIN SysInit */3 `4 w& M I6 t9 H
- + e7 R' Y' f- j; D5 S
- /* USER CODE END SysInit */2 w6 m# R( ~8 f$ }
; {, z9 C D" t# f1 d+ h- /* Initialize all configured peripherals */
+ W9 ~# {5 L; ` p1 l - MX_GPIO_Init();
1 E: b/ i6 d) o& h0 u - MX_USART1_UART_Init();
2 D; g- a% Z* k. J. Q- p - /* USER CODE BEGIN 2 */; j( X( @ ~' O% n9 A
4 _0 O h% P. K8 J: _/ b# P1 ?- /* USER CODE END 2 */
' c5 U8 E' l) j8 ?$ G
7 M5 Q7 Z2 Q, o- /* Infinite loop */2 e- k- _/ U+ |6 p( }9 c6 g
- /* USER CODE BEGIN WHILE */
; W. ^) p" l5 D# s - # t! k* w- o$ v- j' ?/ j9 O9 P
- AT_24c02_int();# y& ^) X) _0 S
- for(i=0;i<BufferSize;i++)2 e9 p& b' z, y: f* R0 J, E
- {
5 T9 q1 k8 H; Y& L - AT_24c02_write_data(data_addr++,WriteBuffer);
3 i( V: [% d; ]3 s) H - HAL_Delay(10);//写完一个字节的数据要记得延时10ms左右,否则会写错1 p9 {2 X" ?: B" D$ ?- _; V, V
- }( M& C$ `# [# R* |
- HAL_Delay(10);& G0 V' ]- `" R6 f' Y' f# Z% W" k
- data_addr = 0x01;# _6 S) S+ o% I
- for(i=0;i<BufferSize;i++)( A% d- F4 N3 x6 n# n- ?" v
- {5 Y3 d$ t9 D3 r# ^
- ReadBuffer = AT_24c02_read_data(data_addr++);
1 g. T& b1 Z: V- J1 U - //HAL_Delay(10);
0 E$ ~1 g+ W7 \% o4 J. J3 b1 ] - }' h- z7 v) x' |7 F6 m
- ' G3 ~2 h5 n; o$ z7 z/ a
- /* 测试输出 */! _ [ I# |3 ]: V4 V* }
- for(i=0;i<BufferSize; i++)
6 K E9 J& e# o& E/ o+ I3 F+ G - {( L; D; u4 t6 D! L: a5 r
- printf("0x%02X\n ",ReadBuffer);) A0 X+ ^) ?- i$ H7 U
- //HAL_Delay(1);
, `0 E; y" K1 T! m - }
+ [1 q( j( C4 V2 V7 E' G" x. X
; F! k7 v% e( H- * f% @; H* a8 A+ U3 u9 D8 a
5 \, @: o4 ^. V8 E- while(1)- y, [, v8 v) n$ c& D- ?! V5 Z
- {" k4 r, @ p* @8 ?0 L
7 z- J. z) Z+ j* ^4 K8 n1 w {( Z- /* USER CODE BEGIN 3 */
! W m6 x* u. l9 w6 [( F4 Q: i3 s - }
' e4 W8 b0 O( F4 p* \, { - /* USER CODE END 3 */1 d. w9 h+ n% {+ W3 ~
- }
复制代码 3 D. t( b# ?+ D5 b
24C02.c; d, Y! y4 A; t# z- N
7 m! G7 S7 e4 S; w, [$ r% g* }, a- void AT_24c02_int(void)9 D" l2 O8 Y. U* X1 F
- {
5 d/ d" j# n3 ^+ y: ~ - IIC_Init();
* P3 y/ H9 _, [$ G* S1 Y! F, b - }
" Q. R U0 q9 k( l* a - //data_addr 字节地址* C% U" c3 A! u
- //data 数据
% _8 c/ M: S [- X& r2 H - void AT_24c02_write_data(uint8_t data_addr,uint8_t data)1 j5 z$ K! a9 E2 e$ O
- {8 U2 L/ H1 T3 B v# q$ @( a3 b. \% Z
- IIC_Start();
# P; c( s" K$ f2 ^( ^- }1 K' {' Y9 L - IIC_Send_Byte(0xa0);8 l& a" q: _* s
- IIC_Wait_Ack();
: Y% h* O& W8 i$ | - IIC_Send_Byte(data_addr);( N/ z3 K+ c9 u F1 M n
- IIC_Wait_Ack();3 k! l3 ^' q* M: ?9 ^6 d. o5 P
- IIC_Send_Byte(data);
9 ~! [3 T- a( V - IIC_Wait_Ack();# G6 y$ [. i+ \1 x* a2 W8 J0 N2 v
- IIC_Stop();
9 F3 _ Z( _/ F: y- q) ]( o! @( p - }! _4 C6 t7 G$ y! o6 v& x2 x6 K
- uint8_t AT_24c02_read_data(uint8_t data_addr)7 `0 C: w S6 z. p6 o7 X
- {, c' R' S* J5 @7 Q. E8 ]6 D P. R
- uint8_t data=0;9 h: L' O$ C$ D! |8 u. H: b
- IIC_Start();
9 [. [# i# [- |% E - IIC_Send_Byte(0xa0);
" l' f1 }0 s$ S4 b! X - IIC_Wait_Ack();
& g# s. h/ q; A' k& I - IIC_Send_Byte(data_addr);2 h6 A5 w( L! O/ h ^5 W( V
- IIC_Wait_Ack();
# W. m& T G$ \- i9 o1 L$ q: L, a - IIC_Start();
* g$ h6 N# U+ M* g5 V - IIC_Send_Byte(0xa1);
/ c' ?8 l2 J* t4 n& |1 F - IIC_Wait_Ack();( ^1 y7 Y2 R5 U4 P1 Q8 e$ l9 M
- data = IIC_Read_Byte();" i% |! |! H3 m7 s3 d9 A: J) U
- IIC_NAck();
4 {- B! ^8 i; q* \$ X - IIC_Stop();9 q% G. V" I4 G! T+ y
- return data;1 v, q, f6 q7 }! L) k8 ^: A
- }
复制代码 0 V) f/ u, y, c( r
作者:jxjajl bilibili3 V. K% J7 M: e, g
4 M" C' Y/ k( q8 q S! o5 `
4 f Q! ]" |2 {1 {& ~4 Z |