你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
举报
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F103的uCOSII详细移植
STM32中BOOT的作用
STM32如何分配原理图IO
STM32的I2S外设
STM32电路知识学习
基于STM32F1的CAN通信之DMA
STM32怎么选型
简单分析STM32和51的区别
简单聊聊STM32的SPI外设
#define PCF8563_GPIO GPIOB3 d* h3 q0 R. A4 A F
#define PCF8563_SDA GPIO_Pin_15
#define PCF8563_SCL GPIO_Pin_14: @3 s* R* Z0 t% W; e6 o
#define Write_ADD 0xA2 //PCF8563的写地址$ s. M' u9 g$ e) S- e- D$ ~) @8 @0 ]
#define Read_ADD 0xA3 //PCF8563的读地址/ S0 r/ X; {/ |6 p4 P+ _, A7 \8 I
3 k* u& ]* P2 P# u
#define PCF8563_Start() IIC_Start(PCF8563_GPIO, PCF8563_SCL, PCF8563_SDA)! U( X/ n# q" f, m: Y
#define PCF8563_Send_Byte(n) IIC_Send_Byte((n), PCF8563_GPIO, PCF8563_SCL, PCF8563_SDA)' A) q% o O; N" r
#define PCF8563_Read_Byte(n) IIC_Read_Byte((n), PCF8563_GPIO, PCF8563_SCL, PCF8563_SDA) g3 X8 ]. g- [3 g
#define PCF8563_Wait_Ack() IIC_Wait_Ack(PCF8563_GPIO, PCF8563_SCL, PCF8563_SDA)& P# v8 ?6 ^: B
#define PCF8563_Stop() IIC_Stop(PCF8563_GPIO, PCF8563_SCL, PCF8563_SDA)
9 R* R4 l+ \$ z# ?$ C
//************************************
// Method: PCF8563_Init9 N; `& r' A; Y9 ~
// FullName: PCF8563_Init
// Access: public - z& m$ X9 m. |' c
// Returns: void, c6 Q% n; T8 W& k$ d/ B" i$ ]
// Parameter: void
// Description: 初始化PCF8563的IO口和寄存器
//************************************
void PCF8563_Init(void) H, d( g H9 D
{ P0 @$ E* p* I0 [' ?
IIC_Init(PCF8563_GPIO, PCF8563_SCL, PCF8563_SDA);
delay_ms(20);
PCF8563_Set(CONTROL_STATUS1, 0x00);
PCF8563_Set(CONTROL_STATUS2, 0x00);
PCF8563_Set(CLKOUT_CONTROL, 0x81); //使能CLK输出,1024Hz: W# R. A) Z) N) j
}6 W } D( z; m: C3 {
. q* x, O" g9 z" p3 F# M- O
//************************************
// Method: PCF8563_Read
// FullName: PCF8563_Read
// Access: public
// Returns: void
// Parameter: PCF8563 * pcf8563) U# s- `! `7 w6 q$ y. s: N' ?3 W
// Description: 读时间 年、月、日、时、分
//************************************ A# T- N. m k0 [4 U
void PCF8563_Read(PCF8563 * pcf8563)3 b% E; H7 Y7 E# G' ]
{0 f1 e$ X# e! S
PCF8563_Start();! x1 |2 U7 L) ?: S
PCF8563_Send_Byte(Write_ADD);
PCF8563_Wait_Ack();% J5 D% R# U) k, z* o
PCF8563_Send_Byte(MINUTES); //分寄存器地址0x037 t T5 e' g' C' g
PCF8563_Wait_Ack();4 X" ~' r! Z0 B1 P
PCF8563_Start();. x+ {5 K) g5 G7 L& V0 X* b
PCF8563_Send_Byte(Read_ADD);
PCF8563_Wait_Ack();
pcf8563->minutes = PCF8563_Read_Byte(1) & 0X7F;
pcf8563->hours = PCF8563_Read_Byte(1) & 0X3F;- c. T7 O! M6 f% A" d8 x1 @
pcf8563->days = PCF8563_Read_Byte(1) & 0X3F;: R* m3 X- }+ M9 d$ a1 y
PCF8563_Read_Byte(1); //读取星期寄存器,该数据不保存( }$ d, b. l) N/ [" [. N
pcf8563->months = PCF8563_Read_Byte(1) & 0X1F;7 _- u) j9 y8 F4 M6 k
pcf8563->years = PCF8563_Read_Byte(0);
PCF8563_Stop(); //发送停止信号. e. R+ s2 a9 m x1 b) [+ R
//将时间从BCD编码变成十进制$ o( l; Z6 ~7 F; V8 y
pcf8563->minutes = BCDToDec(pcf8563->minutes);
pcf8563->hours = BCDToDec(pcf8563->hours);
pcf8563->days = BCDToDec(pcf8563->days);
pcf8563->months = BCDToDec(pcf8563->months);
pcf8563->years = BCDToDec(pcf8563->years);
}
//************************************
// Method: PCF8563_Write
// FullName: PCF8563_Write
// Access: public . L4 a$ [4 S- ^* }; k2 w, ~
// Returns: void7 M0 K, }2 H! M3 ?, ] n
// Parameter: PCF8563 * pcf8563# e# w e# }' x! B U: ]( U
// Description: 将时间(年、月、日、时、分)写入PCF8563% |: q/ F9 e) n& y; T0 G1 ]+ \
//************************************1 V' g) f: N; [# U4 B* W
void PCF8563_Write(PCF8563 * pcf8563)
{$ i% B: F. J2 e- n V# l% V! r
//将时间从十进制变成BCD编码' {. u8 R9 Y$ ^1 l' M
pcf8563->minutes = DecToBCD(pcf8563->minutes);
pcf8563->hours = DecToBCD(pcf8563->hours);
pcf8563->days = DecToBCD(pcf8563->days);
pcf8563->months = DecToBCD(pcf8563->months);2 R& u7 |8 u8 ?
pcf8563->years = DecToBCD(pcf8563->years);6 W1 \' s3 i8 c
6 A U( |9 a7 d- W% F F3 X, V- T% W
PCF8563_Start();
PCF8563_Send_Byte(Write_ADD);
PCF8563_Wait_Ack();/ k8 ]' p/ ]9 w3 I' a% E
PCF8563_Send_Byte(MINUTES); //分寄存器地址0x033 m' f* S# u6 ~2 |
PCF8563_Wait_Ack();! r) D/ a" u3 C5 ~0 M! o; o7 ~
PCF8563_Send_Byte(pcf8563->minutes); //发送分; i$ @3 _$ k# x, j p5 i
PCF8563_Wait_Ack();1 K5 w; N5 @- S5 c* b6 P$ {) T
PCF8563_Send_Byte(pcf8563->hours); //发送时3 g% N# `& U- r* U% Z P7 B
PCF8563_Wait_Ack();$ p* a7 F. @( F: z. R
PCF8563_Send_Byte(pcf8563->days); //发送天
PCF8563_Wait_Ack();
PCF8563_Send_Byte(0x00); //发送星期,不关注星期几 L& Q" Z0 C G2 u1 k+ f! A, h1 o c
PCF8563_Wait_Ack();
PCF8563_Send_Byte(pcf8563->months); //发送月
PCF8563_Wait_Ack();
PCF8563_Send_Byte(pcf8563->years); //发送年
PCF8563_Wait_Ack();* a/ D }6 e4 ^8 c+ t% ]+ X
PCF8563_Stop(); //发送停止信号
}
//************************************
// Method: PCF8563_Set
// FullName: PCF8563_Set$ R2 [. s- F4 D" c0 }
// Access: public
// Returns: void
// Parameter: PCF8563_REGISTER regaddr
// Parameter: unsigned char _data
// Description: 设置寄存器的值
//************************************/ R( z2 l4 B! p( X
void PCF8563_Set(PCF8563_REGISTER regaddr, unsigned char _data); v5 r9 D6 K: K& D3 _' Z9 n
{# C$ V. l' Q } Q' T o! Y
PCF8563_Start();' c: ^6 d6 j. b e% D1 w' ^( o2 e
PCF8563_Send_Byte(Write_ADD);
PCF8563_Wait_Ack();
PCF8563_Send_Byte(regaddr);
PCF8563_Wait_Ack();
PCF8563_Send_Byte(_data);
PCF8563_Wait_Ack();% _# l- e: q: G5 x2 y+ L0 H* H
PCF8563_Stop();1 F }2 R( n/ B2 d8 P" t7 I. u
}) t/ |0 |5 Y! I% I- ?
U1 W" C5 _6 N1 F6 G5 I, O
//************************************
// Method: DecToBCD
// FullName: DecToBCD7 V9 }9 j- ]$ T
// Access: public 1 H0 H* p: S" g$ m: L" `6 h" v7 Z4 m
// Returns: unsigned char: B1 E: k1 q/ ?+ X8 `& Z
// Parameter: unsigned char _dec& L# ~( p3 k, ^% C: d8 D
// Description: 十进制转BCD编码
//************************************
unsigned char DecToBCD(unsigned char _dec)
{5 s" O) X% C. p/ p' c$ w4 S/ Y
unsigned char temp = 0;" g$ ?7 `" ]+ c6 C8 k
while (_dec >= 10)
{# k( X7 g# Q: n3 S, P5 d+ n
temp++;
_dec -= 10;& u5 A5 `4 T: _! Y" M& s
}
return ((unsigned char)(temp << 4) | _dec);
}
//************************************# {2 R! k4 ]+ I% Z* l
// Method: BCDToDec. B) P. _# s: P
// FullName: BCDToDec
// Access: public " P. K7 e5 J2 } O5 w' w. k9 ]
// Returns: unsigned char4 w3 R/ O$ q M0 k! h
// Parameter: unsigned char _BCD6 O; k3 X% l: m$ w% p
// Description: BCD编码转十进制; e# n' y+ l* X% ]3 M
//************************************
unsigned char BCDToDec(unsigned char _BCD)
{$ b' Q. t2 W. r; }! ~0 f( G% h4 {
unsigned char temp = 0;
temp = ((unsigned char)(_BCD & (unsigned char)0xF0) >> (unsigned char)0x04) * 10;
return (temp + (_BCD & (unsigned char)0x0F));: S! Q' @6 y3 a+ n1 a; M
}" B# L$ [8 u4 T% k# C3 H- q
复制代码- N0 Y; b ^" L, b: ^
#include "IIC.h"9 c' ] F; f& e/ G! `6 {# l, F
" T! ]' p5 {: g# T0 T' U4 n; E! n* h
//#define SDA_H() SET_BIT(GPIO->BSRR,SDA_Pin)/ h9 B$ w9 c6 i+ C& Z; g5 t
//#define SDA_L() SET_BIT(GPIO->BRR,SDA_Pin)
//#define SCL_H() SET_BIT(GPIO->BSRR,SCL_Pin)5 k9 J: m5 G4 T$ |' b
//#define SCL_L() SET_BIT(GPIO->BRR,SCL_Pin)6 Z. M' E. C" _$ y- N, r
#define SDA_H() (GPIO->BSRR|=SDA_Pin)
#define SDA_L() (GPIO->BRR|=SDA_Pin)6 t. V& ^( P, `2 _3 V" U
#define SCL_H() (GPIO->BSRR|=SCL_Pin)
#define SCL_L() (GPIO->BRR|=SCL_Pin)& i) g+ s& F$ t* X. F
//************************************ w0 r( P$ w) j# |9 d( _0 z
// Method: IIC_Init- X. E% |& C5 o$ q% `1 x
// FullName: IIC_Init5 i- s' B9 C, |. z
// Access: public
// Returns: void9 {" i& C- y7 V5 K2 @8 O; {1 l
// Parameter: GPIO_TypeDef * GPIO2 h# C- G% {1 k5 o& u) V
// Parameter: uint16_t SCL_Pin8 @! s/ F; P# M& {- x
// Parameter: uint16_t SDA_Pin
// Description: 初始化IIC,设置SDA、SCL为开漏输出,初始为高电平 w* P( o0 Z( N# u
//************************************8 {" d7 L1 ^ m: S; U, g' ]7 h9 T) u
void IIC_Init(GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)
{, L* P+ C; l$ q* O Z5 N. [
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //本次应用中,两个IIC器件均在GPIOB上
$ y. y( C$ ]% H2 x( z
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出' V( _& W, `+ j/ A, Z$ l2 D2 c+ ~' j* o
GPIO_InitStructure.GPIO_Pin = SCL_Pin | SDA_Pin;! @6 X/ @ g6 Y8 s
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;3 H6 s+ G2 y: F4 w
GPIO_Init(GPIO, &GPIO_InitStructure);
//GPIO->BSRR |= SDA_Pin;
//GPIO->BRR |= SCL_Pin;! {; E' j$ O' M7 `8 M
GPIO_SetBits(GPIO, SDA_Pin | SCL_Pin); //SDA、SCL初始状态为高电平
}
4 `, t) g6 I- U* s1 D9 U
//************************************
// Method: IIC_Start
// FullName: IIC_Start
// Access: public ! Z2 n; z# t7 \- ]1 p& ^9 M
// Returns: void3 w; E5 }$ l4 k4 @
// Parameter: GPIO_TypeDef * GPIO& j6 A" k7 X: B: M
// Parameter: uint16_t SCL_Pin
// Parameter: uint16_t SDA_Pin
// Description: 产生起始信号,SCL为高电平时,SDA下降沿
//************************************
void IIC_Start(GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)
{
SDA_H();7 `$ h) J2 ^& y0 Y7 b
SCL_H();( Q5 C2 ^ {1 h) ~7 ]: ]. U3 v7 T
delay_us(4);
SDA_L(); //开始信号
delay_us(4);
SCL_L(); //拉低SCL电平,准备发送或接收数据$ Z" X, k; t4 `% I
}% {8 x- k$ a _9 _- y' q
: R, w; {2 n) W
//************************************7 W, z8 X3 K- R% X! w) x
// Method: IIC_Stop8 m( M/ D' r6 A
// FullName: IIC_Stop
// Access: public
// Returns: void
// Parameter: GPIO_TypeDef * GPIO
// Parameter: uint16_t SCL_Pin
// Parameter: uint16_t SDA_Pin# E* W5 M( i' ]4 T" a( U$ k
// Description: 产生停止信号,SCL为高电平时,SDA上升沿
//************************************ ^/ k O* [1 Q8 Z c% d' u! ]6 t8 X# R* p
void IIC_Stop(GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)
{3 P& Z( w1 Y t: P7 ]
SCL_L();
SDA_L();/ ]$ W$ V! q8 r1 I# @, v7 W: m
delay_us(4);
SCL_H();* _* R1 n) I# a+ E
SDA_H();( ~2 s4 @/ @6 N3 q! E
delay_us(4);
}
1 Z( {3 k$ Z& G/ E( d8 I
//************************************0 S: A* G3 ]4 `
// Method: IIC_Send_Byte* l4 u- j1 }5 n( m6 ^8 \
// FullName: IIC_Send_Byte
// Access: public
// Returns: void
// Parameter: u8 txd9 r& R+ m1 k, P& B3 p
// Parameter: GPIO_TypeDef * GPIO
// Parameter: uint16_t SCL_Pin, {& k* c5 e/ h$ m( q9 m
// Parameter: uint16_t SDA_Pin
// Description: IIC发送一个字节$ p# L5 }7 j1 h3 \2 o6 Q& x
//************************************' U7 x- ]5 R9 k* d- I2 }* }: @
void IIC_Send_Byte(u8 txd, GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin). o3 E' Z) Y- F/ m
{
u8 t;* N& i. k2 Y/ _, C+ ~: l+ m! j/ M
SCL_L(); //拉低时钟开始数据传输
for (t=0;t<8;t++)+ U. |% n2 i0 Y0 ~5 D) h# q Q. ?: M0 X
{
GPIO_WriteBit(GPIO, SDA_Pin, (BitAction)((txd & 0x80) >> 7)); [ L3 @5 z+ _7 _1 E
txd <<= 1;
delay_us(2);
SCL_H();
delay_us(2);
SCL_L();
delay_us(2);) t& s# P: ^( D6 S6 F% d
}+ ~4 n3 ?! [! z- y( `7 R
}$ C0 _4 `& H0 D( w$ r4 H
8 e' f6 g6 b, ^& Z! a
//************************************2 b0 ?! H2 c0 c: [( g7 {
// Method: IIC_Read_Byte
// FullName: IIC_Read_Byte4 _, \# Y. G8 d+ Y; H6 \0 x
// Access: public
// Returns: u82 W, G7 f# B# _8 c/ M1 z1 S
// Parameter: unsigned char ack
// ack=1,发送ACK' F6 X" c+ B, |! ^ S! H$ B
// ack=0,发送NACK
// Parameter: GPIO_TypeDef * GPIO
// Parameter: uint16_t SCL_Pin2 O8 ?4 o/ _. M( u5 ^1 I3 E0 B- R
// Parameter: uint16_t SDA_Pin
// Description: 读一个字节,SCL低电平时,改变SDA
//************************************2 Y& o3 H; w( w+ H; e( t
u8 IIC_Read_Byte(unsigned char ack, GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)& E9 V, }6 f: K) A: h& p
{
unsigned char i, receive = 0;
SDA_H(); //释放总线
for (i = 0; i < 8; i++)% r8 f1 K% F* [3 p7 y$ J2 U
{( }) y0 G9 A. Q9 H/ Y A9 r4 b! V
SCL_L();
delay_us(2);2 V- y. R2 f. `* a4 x
SCL_H();9 s! |) q4 ^/ z g) x: p
receive <<= 1;
if (GPIO_ReadInputDataBit(GPIO, SDA_Pin))
{
receive++;
}' c$ d* O% q# \+ h
//receive |= READ_BIT(GPIO->IDR, SDA_Pin);
delay_us(1);, q8 [% _- s' H& M: Q1 H
}
if (!ack)
IIC_NAck(GPIO, SCL_Pin, SDA_Pin);//发送nACK S* K% n. u8 H0 k! J
else
IIC_Ack(GPIO, SCL_Pin, SDA_Pin); //发送ACK 2 Y1 C h4 u0 A& ]5 }2 K
return receive;
}: q" Y: R* |3 Q' t ~
//************************************# A5 b/ x" C6 B/ h- J
// Method: IIC_Wait_Ack0 c4 y0 n. C# \5 L
// FullName: IIC_Wait_Ack! P- t: f* [: l3 v. x$ q
// Access: public
// Returns: u8 1-接收应答失败,0-接收应答成功$ Z; n( v2 E2 p1 o7 j8 L
// Parameter: GPIO_TypeDef * GPIO
// Parameter: uint16_t SCL_Pin
// Parameter: uint16_t SDA_Pin
// Description: 等待应答信号到来. b3 `9 J. r$ a1 y( m
//************************************! f5 s2 }' e7 g) M
u8 IIC_Wait_Ack(GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)5 }3 r4 _, m% R9 y; V
{* c& G# `; D( p1 ]2 w9 b8 |0 q
u8 ucErrTime = 0;
SDA_H(); //释放总线8 ]! d$ B( w; W! J. x5 g0 W
delay_us(1);4 |: Z; T. I# x4 `
SCL_H();, U; X/ L/ `7 a# e! u, [9 H
delay_us(1);
while (READ_BIT(GPIO->IDR,SDA_Pin))7 V% S( E$ ^6 Q b
{
ucErrTime++;* x$ Q. H: r# h
if (ucErrTime > 250)" d) G; R( v6 R) u% Y
{+ B7 j1 i9 H. l" k* r0 j
IIC_Stop(GPIO, SCL_Pin, SDA_Pin);+ U2 M9 H; u2 ?- i
return 1;
}$ h! M+ r2 F5 V
}' m1 Q s* j+ e, P* B
SCL_L(); $ {$ h! S/ ^% v; k: S( o/ f
return 0;4 y" y) N2 z1 K# E4 F8 p
}
//************************************
// Method: IIC_Ack. `" \) u- M/ Y9 O2 ], y
// FullName: IIC_Ack& R6 Y& C3 v: i5 k5 y
// Access: public 9 A- h0 e7 G5 o' G
// Returns: void0 M, O/ P( y: D& M: o: j
// Parameter: GPIO_TypeDef * GPIO
// Parameter: uint16_t SCL_Pin P6 f5 L* A& { b4 |+ o- d1 p: h
// Parameter: uint16_t SDA_Pin
// Description: 产生ACK应答,设备在接收或发送到一个字节后能拉低SDA电平
//************************************
void IIC_Ack(GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)
{% J" u9 x& |, z$ Z
SCL_L();. i0 v6 n1 g# k
SDA_L();
delay_us(2);
SCL_H();
delay_us(2);: M$ e1 P% Y( a* l
SCL_L();7 ]1 O9 d0 Y+ q/ K3 l/ X* d
}
5 O( H8 ?+ o2 i8 W [ N: P
//************************************
// Method: IIC_NAck5 O# p- ?' x7 d3 D0 S- Q% m
// FullName: IIC_NAck
// Access: public
// Returns: void
// Parameter: GPIO_TypeDef * GPIO
// Parameter: uint16_t SCL_Pin' Z0 \8 D$ h/ I: Y0 J" C
// Parameter: uint16_t SDA_Pin" F' J+ ^. h; g3 B$ F! `
// Description: 产生NACK应答,设备在接收或发送到一个字节后能拉低SDA电平
//************************************
void IIC_NAck(GPIO_TypeDef * GPIO, uint16_t SCL_Pin, uint16_t SDA_Pin)
{( U2 g: ]( _, C8 K* L
SCL_L();
SDA_H();# a' }& ]) X" z3 t4 V% ~4 D/ C
delay_us(2);- h9 U4 A5 |9 w% p$ }( F9 D
SCL_H();
delay_us(2);
SCL_L();
}% V" }, ?% k/ L) C6 O1 g