项目简介( ?% r0 U+ X4 [6 W+ m( R# |
利用CubMX生成基于32单片机的HAl库工程,然后编写程序在proteus上仿真验证。本项目最适合没有开发板的同学学习,零成本利用仿真软件率先入门STM32单片机。这是第四部分针对EEPROM 24C02的一个实例,IIC通信是一种比较典型的串行通信方式,在很多情况下都会有所使用,了解并熟悉IIC通信就显得十分重要。本项目之所以使用模拟IIC,而没有使用STM32单片机内置的硬件IIC,主要由于Half库里IIC的坑太多了,自己一开始也是想通过HAL库来开发,但是始终不成功,也有可能仿真软件也有些坑,如果有能够做出来的大佬,也欢迎评论区或私聊我交流,不过在实物32单片机开发板上网上好像验证过可用,但是手上暂时缺开发板,针对硬件IIC这一块的内容,以后有时间会完善。
# {% Z @( q4 {1 H
9 N& {: r2 l% p硬件模块" k9 G; t2 g: `4 ` L4 |- n
STM32F103R4
" Z- o8 ^1 e: y 24C02
, N7 M" q C8 x$ v" I0 x 串口模块2 ~, U! k4 r4 T# k# u
& J: ^: E, s$ Q# e软件工具
1 T, U# j ^$ i CubMX$ m) O- L/ ]1 _. }" u6 w; [$ ~; I
Proteus
& Z# X& e, P, O9 y: W KEIL. ~2 g# C" |4 Y) i# S2 {/ B
E1 _3 }3 l( r* K& w电路连接图9 D* W" J. M, w1 \& z
- p: q" `2 Y' ~
% k% X3 m* J7 p3 ^& c& n' L- q* c P4 i% A/ K5 Q
1 f! j8 r% s' Y' P6 y0 w5 F- l
0 L, Z) ~6 m& z* M, k+ E7 a
工作流程% f4 U+ C" [$ K6 \8 A
首先创建一个CubMX工程,如果是配置硬件IIC很容易,只要简单选择一下就可以了1 s8 F2 h9 S+ b5 q( e+ d
8 j8 z- F. ]! B! r7 o2 @: x! L, N
2 q2 ^8 G3 n4 V( d
- e3 r7 Z! `8 v) y: C( y3 { 默认是标准模式,速度是100kHz,可以选择高速模式400kHz,其余可以保持默认,当然这是硬件IIC的配置方法,咱们用的是模拟IIC,相应的引脚设置在后面生成的Keil工程里编写相应程序即可。
0 C8 S6 L D! X$ s) {% a& O5 \$ T; u' q
2 u J0 b. U3 S7 r& K8 ~( L2 k
$ { o8 x( m0 U' ?
其余也是保持默认即可9 s9 V) o) S' S% n9 `9 C6 S I
( B$ d6 y7 U- @' @
9 v/ g. D, Y' l
7 A# z2 D- Z4 o! X% ~
0 K, I/ _ j. G# C* h& l/ n9 `0 K* l
0 Y5 w/ P7 }$ G! w7 h 之后,在生成的KEIL工程中编写相应的程序,这部分在后面会列出。/ v7 N0 l; q) i J$ C/ d9 X
( U3 _/ M7 U) ?- F 然后就是验证了。将提前设置的一组数据写入进24C02中,然后从24C02中读取出来,并用串口打印,提前设置的数据是{1,2,3,4,5,6,7,0} ,串口打印出的数据如下:5 q+ _; {8 e* G+ e. [, }# o
' H+ S6 w" U" W6 G
- A: G) E. ]" Y* G9 ~1 C
6 e* G+ ?) h0 ^1 I% v程序代码( P! H8 L. O) j% T" M
main.c# P1 {! I' }6 Y" Q I% D- C1 ?, Q1 n
- uint8_t WriteBuffer[2*BufferSize] = {1,2,3,4,5,6,7,0}; //需要写的数据在WriteBuffer当中: J, i) q5 E% @/ d2 T: q" @( k
- uint8_t ReadBuffer[2*BufferSize]={0}; //读出来的数据放进ReadBuffer当中
5 X; x5 Q/ R! W# x$ `! [! q2 O - uint8_t i;- r, k) D( k6 d6 u) s% G
- uint8_t data_addr = 0x01;
# f0 b/ N8 s, {6 ] - /* USER CODE END 0 */! J9 f1 a4 K$ b" ?. i5 j
; H+ _2 `( S: @9 y- S3 [0 f+ K- //重定向printf()到串口发送和接收,方便应用
% b' P0 b3 f+ M- V# t - int fputc(int ch, FILE *f){
3 ?5 V6 ?. f8 k5 D: T+ d8 Z - uint8_t temp[1] = {ch};% R! E% u- Z1 l& }
- HAL_UART_Transmit(&huart1, temp, 1, 0xffff);% ?3 f1 G0 O) D; O% P$ A
- return ch;
( d P! f" r% N) E - }
! w$ E. d0 p3 l4 H) u0 g+ l- N - //重定向scanf()函数和getchar()函数,方便应用
5 ]1 K! O# j. b7 V! ~; u - int fgetc(FILE * f); o I+ h( a# J8 B# m0 c9 W
- {' H' d3 J* P! Y' W9 P
- uint8_t ch = 0;; g7 k5 {( B; v4 c3 T7 j8 G
- HAL_UART_Receive(&huart1,&ch, 1, 0xffff); c; K' ~4 ]- x5 j! S2 r+ ?
- return ch;/ d5 K7 D; L2 x5 J; x: _% i" t
- }
8 q5 q7 k. c a. A; V - & u: R/ `) g% \+ J4 F5 o
- /**0 b1 L, V7 a8 i7 `( U0 P. Q% \
- * @brief The application entry point.
3 v: R' o0 F: o2 k: z* I7 D0 Q - * @retval int! A. P" y* k# e; d" b
- *// ?& Q' Q" o0 |9 _( z
- int main(void)
/ v0 w& i4 k! J( [1 o - {
% Q0 n3 x/ V- t - /* MCU Configuration--------------------------------------------------------*/
! J- R) h2 X# e - - |! f" L7 V7 Z' y9 @
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */3 O6 U# I9 P; H: o4 R" X1 j
- HAL_Init();) F& Q% C% |; t2 V( p, x* Q
+ |; f$ o8 ^3 s) N- /* USER CODE BEGIN Init */
3 H: J# g( t P! j( ?8 X. J
7 Z. `. P2 _6 o4 r' ^& Q8 m( I- /* USER CODE END Init */
# _* U/ `) ?; [ M+ k3 q6 Q g( p( {1 {
1 t/ t" G" d( a+ K) T( `- /* Configure the system clock */& w% ?% t5 N7 k) Y5 }! b, Y
- SystemClock_Config();
' I) e& P+ I7 L% k# `
; v1 L1 D( F7 s+ D6 `- /* USER CODE BEGIN SysInit */
. J: h1 N% `% N. o9 R9 e0 U2 |* X1 m
6 R( w- ?# Q' T: H6 x- /* USER CODE END SysInit */
: H8 `7 L# U% F1 w7 z, T3 Y: t$ H/ {
; B* [% z3 k/ p) J: g- /* Initialize all configured peripherals */( g! z2 V2 Z3 c) n
- MX_GPIO_Init();; ~. o Q/ R4 j
- MX_USART1_UART_Init();- L6 \* K( ~6 h6 e9 X$ ?3 j
- /* USER CODE BEGIN 2 */
- l8 K6 |# r% l5 k7 E
: G6 Q% o# W% E- /* USER CODE END 2 */
0 h, @% W& L8 K2 I. |4 p - / O6 x2 \8 C& v9 j: |" y2 M& o
- /* Infinite loop */( b( q7 q7 L4 l0 q t' [
- /* USER CODE BEGIN WHILE */
S) e/ T1 R0 C/ q+ X& y. F' f: h - " v# _* C$ d6 F5 {
- AT_24c02_int();6 H$ k4 X- i- ]! @+ o$ j
- for(i=0;i<BufferSize;i++)4 y8 [8 e: u% `4 \$ E" l
- {9 P8 d- B. L1 E9 G
- AT_24c02_write_data(data_addr++,WriteBuffer[i]);
1 [9 k- K/ E4 o( n7 O3 R - HAL_Delay(10);//写完一个字节的数据要记得延时10ms左右,否则会写错2 D5 C6 n& c9 u( W2 p0 K/ Y
- }! J+ G D% P' X0 [' k) w
- HAL_Delay(10);7 m2 f* K( d; J; r
- data_addr = 0x01;: p- _. _' O) I- ~2 p+ q
- for(i=0;i<BufferSize;i++)5 t- ~) G$ m2 C; N" j( R: V7 d' z
- {
5 t' l/ M8 ^; s, J3 } - ReadBuffer[i] = AT_24c02_read_data(data_addr++);: J+ x0 l5 r0 N
- //HAL_Delay(10);3 q4 o# j- C' w. U* ]9 M
- }
- W |+ ^- p% {4 J - + ^: r3 q# [( g$ _" B
- /* 测试输出 */& N, a7 u& U i" B
- for(i=0;i<BufferSize; i++)
' h! I5 \0 g4 r, t - {) h3 P7 a% ]3 v" Y) y1 ?% f1 I8 X
- printf("0x%02X\n ",ReadBuffer[i]);
5 r/ x- o M3 C( A - //HAL_Delay(1);
7 B" s0 h2 X) G3 i - }
2 L& x* t1 a! o% F - 4 i) b9 e' C5 \4 k: f$ ` A$ F, a
8 q2 v' Q1 _, p+ M$ d2 R+ h" X& [
0 ~; `1 |# {7 B8 F8 U& N# @- while(1)
! B* i/ U& \6 H1 B A. Q1 x - {6 Y" V6 V0 b8 F- B2 i2 q+ p
+ _+ a8 J- q6 m- /* USER CODE BEGIN 3 */. Y6 w. s" O# r% }% N& N2 L+ P: j5 R
- }3 D. c Q( C7 X9 z& L8 g
- /* USER CODE END 3 */
5 E6 n1 V% f/ x# h - }
复制代码 % d7 {' r( h7 y. L
24C02.c: Y' g5 _; E$ { x: c1 p" w
- void AT_24c02_int(void)5 W, [7 a0 |/ L4 |: N+ D1 }
- { a9 o8 i$ k) z
- IIC_Init();' K, s: |/ n- `- H) s {
- }
/ j0 f. M$ Y% Q0 T - //data_addr 字节地址
% D% m& u, X" Q3 ? - //data 数据1 k# c$ x$ e$ q/ t4 Q- z) i- {
- void AT_24c02_write_data(uint8_t data_addr,uint8_t data)
. j! F% a6 y$ N- j7 I - {
; a& y: u3 R- E9 v% G1 f5 h1 s - IIC_Start(); O: g. }0 Z' I* R" o3 N& P& K2 j
- IIC_Send_Byte(0xa0);6 L) D+ l( M2 P, F0 g/ Q$ v
- IIC_Wait_Ack();
4 h! j# b4 Y, p& M' N - IIC_Send_Byte(data_addr); u! p8 d9 W5 \8 p' g% S3 E
- IIC_Wait_Ack();
' ^: v1 n" n( [ m! j A L - IIC_Send_Byte(data);
, u1 y/ o6 c( X - IIC_Wait_Ack();' n$ y/ s/ d b2 H! J7 V; t
- IIC_Stop();
# @( {2 r) u$ i6 [) I - }
) z, Z/ `* N- c0 B - uint8_t AT_24c02_read_data(uint8_t data_addr); D' A& ~4 i& r/ y
- {
; i0 o0 x5 |# v- r - uint8_t data=0;
: f7 s( I1 o, S9 E- i/ O s `0 z8 a9 j - IIC_Start();* `" k* a% o% ^; ~
- IIC_Send_Byte(0xa0);
9 b) V8 d' W) I - IIC_Wait_Ack();
* V- F9 s+ A* Y2 P4 r d4 S% [ - IIC_Send_Byte(data_addr);+ {6 s( G7 t5 C9 d$ |$ V3 C+ e
- IIC_Wait_Ack();
. e# Q; ~6 N! G) o K - IIC_Start();9 Q8 n8 ], v# i' @# z5 z
- IIC_Send_Byte(0xa1);
2 V0 u' m( B2 x% L - IIC_Wait_Ack();
" ]. l4 g8 G5 M4 e+ B0 l* q - data = IIC_Read_Byte();
8 }; Q3 D3 L* I2 l% x8 v* o0 E - IIC_NAck();
/ m! S7 w4 t6 p. s - IIC_Stop();
% L4 t3 m! A* P( W% E5 ~' r - return data;$ L Q/ Z/ l" U( n* J( x) z# L
- }
复制代码 1 ~! J ]$ Q4 s$ t: ^+ k) y% T
作者:jxjajl * B! J4 G! Z6 O, S" X
) u& i* O0 v$ n: O: } |