簡述一下除錯的心酸歷程,剛開始用的32硬體iic,眼看馬上就要讀出資料了,可是硬體iic在讀取ccs811的0x02據暫存器的時候不能給每乙個接收到的位元組產生應答,導致ccs811只發出乙個正確的位元組,又不得不改為模擬iic,有關晶元的知識就不在這多介紹了,具體流程如圖
步驟1:讀ccs811的id
` void ccs_read_id(void)`
步驟2:從boot模式到應用模式
void ccs_ht_mode(void)
步驟3:讀0x00暫存器看是否進入了應用模式
void ccs_chkworkmode(void )
步驟4:設定暫存器0x01,設定讀取間隔時間
void ccs_setreadmode(void)
步驟5:讀取co2濃度,8位元組0x02暫存器,我這裡只讀取了兩個位元組
void read_co2ppm(void)
}
#define scll1 hal_gpio_writepin(gpiob, gpio_pin_6, gpio_pin_reset);
#define sclh1 hal_gpio_writepin(gpiob, gpio_pin_6, gpio_pin_set);
#define sdal1 hal_gpio_writepin(gpiob, gpio_pin_7, gpio_pin_reset);
#define sdah1 hal_gpio_writepin(gpiob, gpio_pin_7, gpio_pin_set);
#define sda_state hal_gpio_readpin(gpiob, gpio_pin_7)
void ccs_io_init(void)
void sda_in(void)
void sda_out(void)
//sysclk:系統時鐘
void delay_init(u8 sysclk)
void delay_us(u32 nus)
while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達
systick->ctrl=0x00; //關閉計數器
systick->val =0x00; //清空計數器
}//接收乙個位元組
u8 rcvbyte(void)
}scll1;
delay_us(50);
return retc;
} void iic_start(void)
void iic_stop(void)
u8 iic_wait_ack(void)
}delay_us(30);
scll1;//時鐘輸出0
//啟動模式
delay_us(200);
i2c1_write_bety(0xb4);
while(!(i2c1->sr1 & (1 << 7)));//傳送完成
i2c1->cr1 |= 1 << 9;//置為,產生停止條件
//監測是否進入測量模式
i2c1_write_bety(0xb4);
i2c1->dr = ccs_staus_reg;//將從機位址寫入資料暫存器
while(!(i2c1->sr1 & (1 << 7)));//傳送完成
i2c1->cr1 |= 1 << 9;//置為,產生停止條件
i2c1_write_bety(0xb5);
ustaus = i2c1_read_bety();
//printf("3");
if(!(ustaus&(1<<7)))
delay_us(1000000);
i2c1_write_bety(0xb4);
i2c1->dr = ccs_measmode_reg;//將從機位址寫入資料暫存器
while(!(i2c1->sr1 & (1 << 7)));//傳送完成
i2c1->dr = 0x10;
while(!(i2c1->sr1 & (1 << 7)));
i2c1->cr1 |= 1 << 9;//置為,產生停止條件
i2c1_write_bety(0xb4);
i2c1->dr = ccs_measmode_reg;//將從機位址寫入資料暫存器
while(!(i2c1->sr1 & (1 << 7)));//傳送完成
i2c1->cr1 |= 1 << 9;//置為,產生停止條件
i2c1_write_bety(0xb5);
i2c1_read_bety();
printf("ccs811init.ok............");
gpublictimer.isreadco2time = t_1s;//讀取
uint8_t rxdata = 0;
i2c1_write_bety(0xb4);
i2c1->dr = ccs_staus_reg;//將從機位址寫入資料暫存器
while(!(i2c1->sr1 & (1 << 7)));//傳送完成
i2c1->cr1 |= 1 << 9;//置為,產生停止條件
i2c1_write_bety(0xb5);
rxdata = i2c1_read_bety();
uint8_t co2ppm[2] =;
if(rxdata&(1<<3)){
i2c1_write_bety(0xb4);
i2c1->dr = ccs_algres_data;//將從機位址寫入資料暫存器
while(!(i2c1->sr1 & (1 << 7)));//傳送完成
i2c1->cr1 |= 1 << 9;//置為,產生停止條件
i2c1_write_bety(0xb5);
while(!(i2c1->sr1 & (1 << 6)));//判斷rxne是否置位
co2ppm[0] = i2c1->dr ;
delay_us(150);
i2c2->cr1 |=(1<< 10);
while(!(i2c1->sr1 & (1 << 6)));//判斷rxne是否置位
co2ppm[1] = i2c1->dr ;
i2c2->cr1 &=~(1<< 10);
i2c1->cr1 |= 1 << 9;//產生停止條件
printf("co2ppm = %x\r\n",(co2ppm[0]<<8)+co2ppm[1]);
STM32之I2C模組除錯總結
前一段時間對stm32的i2c模組進行了除錯,今天做乙個總結。關於i2c協議的知識,這裡就不再贅述,網上有很多介紹i2c協議的文章。目前實現i2c協議的方式有兩種,一是採用gpio口來模擬i2c協議,另外一種是使用stm32自帶的i2c模組。雖說使用gpio口模擬i2c協議較為複雜,需要詳細了解i2...
STM32 軟體模擬I2C
i2c的兩個引腳 scl引腳和sda引腳 需要既能輸出又能輸入,為了避免複雜的配置操作需要把該引腳配置為開漏輸出模式,該模式的說明如下圖所示 當微控制器的sda引腳配置為低電平時,sda線被拉低 當微控制器的sda引腳配置為高電平時,引腳埠為高阻態,sda線通過上拉電阻被vcc拉高。因此一定要注意在...
STM32之I2C 學習筆記
1 i2c是兩線式序列匯流排,由資料線sda和時鐘scl構成的序列匯流排,可傳送和接收資料。在cpu與被控ic之間 ic與ic之間進行雙向傳送,高速iic匯流排一般可達400kbps以上。2 iic是半雙工通訊方式,也就是說它既可以接收也可以傳送,但是由於它只有一根資料線,所以接收和傳送不能同時進行...