基於STM32的I2C除錯CO2感測器CCS811

2021-09-19 18:43:22 字數 3844 閱讀 6649

簡述一下除錯的心酸歷程,剛開始用的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是半雙工通訊方式,也就是說它既可以接收也可以傳送,但是由於它只有一根資料線,所以接收和傳送不能同時進行...