這段時間在做全國光電設計大賽,用到了px4的px4flow光流感測器,用軟體模擬iic讀取數據不定期會導致px4flow死機,查了資料和光流的源碼,發現這個光流用了stm32的硬體iic,所以對軟體模擬iic的時序要求可能更高一點所以在原子哥的iic程式上做了修改,代碼測驗後已經不會死機,做個筆記, ...
這段時間在做全國光電設計大賽,用到了px4的px4flow光流感測器,用軟體模擬iic讀取數據不定期會導致px4flow死機,查了資料和光流的源碼,發現這個光流用了stm32的硬體iic,所以對軟體模擬iic的時序要求可能更高一點所以在原子哥的iic程式上做了修改,代碼測驗後已經不會死機,做個筆記,保存一下。
1 #include "myiic.h"
2 #include "delay.h"
15
16 //初始化IIC
17 void IIC_Init(void)
18 {
19 GPIO_InitTypeDef GPIO_InitStructure;
20
21 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB時鐘
22
23 //GPIOB10,B11初始化設置
24 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
25 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通輸出模式
26 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推輓輸出
27 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
28 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
29 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
30 IIC_SCL=1;
31 IIC_SDA=1;
32 }
33 //產生IIC起始信號
34 void IIC_Start(void)
35 {
36 SDA_OUT(); //sda線輸出
37 IIC_SDA=1;
38
39 delay_us(1);
40
41 IIC_SCL=1;
42 delay_us(2); //4
43 IIC_SDA=0;//START:when CLK is high,DATA change form high to low
44 delay_us(2); //4
45 IIC_SCL=0;//鉗住I2C匯流排,準備發送或接收數據
46 }
47 //產生IIC停止信號
48 void IIC_Stop(void)
49 {
50 SDA_OUT();//sda線輸出
51 IIC_SCL=0;
52
53 delay_us(1);
54
55 IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
56 delay_us(2); //4
57 IIC_SCL=1;
58
59 delay_us(1);
60
61 IIC_SDA=1;//發送I2C匯流排結束信號
62 delay_us(2); //4
63 }
64 //等待應答信號到來
65 //返回值:1,接收應答失敗
66 // 0,接收應答成功
67 u8 IIC_Wait_Ack(void)
68 {
69 u8 ucErrTime=0;
70 SDA_IN(); //SDA設置為輸入
71 IIC_SDA=1;
72 delay_us(1); //1
73 IIC_SCL=1;
74 delay_us(1); //1
75 while(READ_SDA) //可能可以把數搞大點
76 {
77 ucErrTime++;
78 if(ucErrTime>250)
79 {
80 IIC_Stop();
81 return 1;
82 }
83 }
84 IIC_SCL=0;//時鐘輸出0
85 return 0;
86 }
87 //產生ACK應答
88 void IIC_Ack(void)
89 {
90 IIC_SCL=0;
91
92 delay_us(1);
93
94 SDA_OUT();
95 IIC_SDA=0;
96 delay_us(2); //2
97 IIC_SCL=1;
98 delay_us(2); //2
99 IIC_SCL=0;
100 }
101 //不產生ACK應答
102 void IIC_NAck(void)
103 {
104 IIC_SCL=0;
105
106 delay_us(1);
107
108 SDA_OUT();
109 IIC_SDA=1;
110 delay_us(2); //2
111 IIC_SCL=1;
112 delay_us(2); //2
113 IIC_SCL=0;
114 }
115 //IIC發送一個位元組
116 //返回從機有無應答
117 //1,有應答
118 //0,無應答
119 void IIC_Send_Byte(u8 txd)
120 {
121 u8 t;
122 SDA_OUT();
123 IIC_SCL=0;//拉低時鐘開始數據傳輸
124 for(t=0;t<8;t++)
125 {
126 IIC_SDA=(txd&0x80)>>7;
127 txd<<=1;
128 delay_us(2); //對TEA5767這三個延時都是必須的 //2
129 IIC_SCL=1;
130 delay_us(2); //2
131 IIC_SCL=0;
132 delay_us(2); //2
133 }
134 }
135 //讀1個位元組,ack=1時,發送ACK,ack=0,發送nACK
136 u8 IIC_Read_Byte(unsigned char ack)
137 {
138 unsigned char i,receive=0;
139 SDA_IN();//SDA設置為輸入
140 for(i=0;i<8;i++ )
141 {
142 IIC_SCL=0;
143 delay_us(2); //2
144 IIC_SCL=1;
145 receive<<=1;
146 if(READ_SDA)
147 receive++;
148 delay_us(2); //1
149 }
150 if (!ack)
151 IIC_NAck();//發送nACK
152 else
153 IIC_Ack(); //發送ACK
154 return receive;
155 }
空行間隔的為新增延時,和註釋不一樣的為改了的延時