Недавно я приобрел у Adafruit плату для датчика температуры и влажности SI7021. Он использует протокол I2 C, и я относительно новичок в I2 C, я имею в виду, я знаю, как он работает теоретически, но я никогда не писал никакого кода для него. Я использую микроконтроллер STM32F407 от STM и CodeBlocks в качестве моей платформы программирования. Я нашел несколько примеров программ, но все они были для Кейла (я думаю, что это называется) и использовали функции HAL, которые я не могу использовать, и большинство из них смутило меня. Дело в том, что я сделал эту программу, используя пример программы из моего сценария, который я получил в школе, и я также снимал части из видео на YouTube, используя функции HAL. Итак, я в основном взял 2 разные программы и смешал их в одну.
Вот таблица данных датчика, который я использую: https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf На странице 20 в таблице данных вы можете увидеть две разные способы связи с датчиком, я решил попробовать тот, который называется: «Hold Master Mode».
Видео YouTube, о котором я упоминал выше: https://www.youtube.com/watch?v=3JrLBHetzn8
#include "SmartcontrolOS.h"
#include "CMSIS.h"
#define DAC_DHR12R1_ADDRESS 0x40007408
#define CODEC_FLAG_TIMEOUT ((uint32_t)0x2000)
#define CODEC_LONG_TIMEOUT ((uint32_t)(300 * CODEC_FLAG_TIMEOUT))
__IO uint32_t CODECTimeout = CODEC_LONG_TIMEOUT;
uint32_t Codec_TIMEOUT_UserCallback(char* caller){
while (1) { /* Block communication and all processes */
}
}
ui32 loop_while_stop_flag_is_set(){
CODECTimeout = CODEC_FLAG_TIMEOUT;
while(I2C1->CR1 & I2C_CR1_STOP) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f8");}
return 0;
}
ui32 loop_till_event(uint32_t flag){
CODECTimeout = CODEC_FLAG_TIMEOUT;
while (!I2C_CheckEvent(I2C1, flag)){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f2");}
return 0;
}
ui32 loop_while_flag_is(uint32_t flag, Bool level){
CODECTimeout = CODEC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, flag)==level){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f1");}
return 0;
}
void Auswertung(){
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); /* Enable the I2C1 peripheral clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef
GPIO_InitStructure = {0};
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); /* I2C SCL pin Configuration */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); /* I2C SDA pin Configuration */
/* I2C1 peripheral configuration */
I2C_DeInit(I2C1);
I2C_InitTypeDef
I2C_InitStructure = {0};
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x33;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE); /* Enable the I2C peripheral */
int Sensor_Adresse = 0x40;
ui8 Data[2] = {0};
ui8 index = 0;
ui16 temp_code = 0;
ui16 humidity_code = 0;
//HUmidity
//Writing Section
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1, ENABLE);
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);
loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
I2C_SendData(I2C1,0xE5);
//Reading Section
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1,ENABLE);
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);
loop_while_flag_is(I2C_FLAG_BTF,0);
I2C_GenerateSTART(I2C1,ENABLE);
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Receiver);
loop_while_flag_is(I2C_FLAG_ADDR,0);
loop_while_flag_is(I2C_FLAG_RXNE,0);
Data[index++] = I2C_ReceiveData(I2C1);
index = 0;
humidity_code = ((Data[0] <<8) | Data[1]);
//Temperature
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1, ENABLE);
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);
loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
I2C_SendData(I2C1,0xE0);
//Reading Section
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1,ENABLE);
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);
loop_while_flag_is(I2C_FLAG_BTF,0);
I2C_GenerateSTART(I2C1,ENABLE);
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Receiver);
loop_while_flag_is(I2C_FLAG_ADDR,0);
loop_while_flag_is(I2C_FLAG_RXNE,0);
Data[index++] = I2C_ReceiveData(I2C1);
index = 0;
temp_code = ((Data[0] <<8) | Data[1]);
float Humidity = 0;
float Temperature = 0;
Humidity = ((125.0f * humidity_code) / 65536.0f) - 6.0f;
Temperature = ((175.72f * temp_code) / 65536.0f) - 46.85f;
LCD__write(_,"%15.2f\n%15.2f",wf(Temperature),wf(Humidity));
}
void CPE_App__Wetterstation_I2C_RH_T(){
Resources__ExBoard_init(_,"");
while(1){
Auswertung();
}
}
Надеюсь, вы поможете мне лучше понять I2 C и программирование в целом, а также завершить эту программу. Хорошего дня.
Редактировать: После просмотра этого поста я понял, что не добавил вторую программу, о которой говорил, так что вот она. Это из моего сценария, который я получил из школы.
#include "SmartcontrolOS.h"
#include "CMSIS.h"
#define CODEC_FLAG_TIMEOUT ((uint32_t)0x2000)
#define CODEC_LONG_TIMEOUT ((uint32_t)(300 * CODEC_FLAG_TIMEOUT))
#define CODEC_ADDRESS 0x94 /* b00100111 */
#define CODEC_STANDARD 0x04
__IO uint32_t CODECTimeout = CODEC_LONG_TIMEOUT;
uint32_t Codec_TIMEOUT_UserCallback(char* caller){
while (1) { /* Block communication and all processes */
LCD__write(_, caller);
}
}
ui32 loop_while_stop_flag_is_set(){
CODECTimeout = CODEC_FLAG_TIMEOUT;
while(I2C1->CR1 & I2C_CR1_STOP) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f8");}
return 0;
}
ui32 loop_till_event(uint32_t flag){
CODECTimeout = CODEC_FLAG_TIMEOUT;
while (!I2C_CheckEvent(I2C1, flag)){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f2");}
return 0;
}
ui32 loop_while_flag_is(uint32_t flag, Bool level){
CODECTimeout = CODEC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(I2C1, flag)==level){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f1");}
return 0;
}
static uint32_t Codec_ReadRegister(uint8_t RegisterAddr){
uint32_t result = 0;
loop_while_flag_is(I2C_FLAG_BUSY,1); /*!< While the bus is busy */
I2C_GenerateSTART(I2C1, ENABLE); /* Start the config sequence */
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT); /* Test on EV5 and clear it */
I2C_Send7bitAddress(I2C1, CODEC_ADDRESS, I2C_Direction_Transmitter); /* Transmit the slave address and enable writing operation */
loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); /* Test on EV6 and clear it */
I2C_SendData(I2C1, RegisterAddr); /* Transmit the register address to be read */
loop_while_flag_is(I2C_FLAG_BTF, 0); /*!< Wait till all data have been physically transferred on the bus */
I2C_GenerateSTART(I2C1, ENABLE); /*!< Send START condition a second time */
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT); /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
I2C_Send7bitAddress(I2C1, CODEC_ADDRESS, I2C_Direction_Receiver); /*!< Send Codec address for read */
loop_while_flag_is(I2C_FLAG_ADDR,0); /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
I2C_AcknowledgeConfig(I2C1, DISABLE); /*!< Disable Acknowledgment */
(void)I2C1->SR2; /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
I2C_GenerateSTOP(I2C1, ENABLE); /*!< Send STOP Condition */
loop_while_flag_is(I2C_FLAG_RXNE,0); /* Wait for the byte to be received */
result = I2C_ReceiveData(I2C1); /*!< Read the byte received from the Codec */
loop_while_stop_flag_is_set(); /* Wait to make sure that STOP flag has been cleared */
I2C_AcknowledgeConfig(I2C1, ENABLE); /*!< Re-Enable Acknowledgment to be ready for another reception */
I2C_ClearFlag(I2C1, I2C_FLAG_AF); /* Clear AF flag for next communication */
return result; /* Return the byte read from Codec */
}
static uint32_t Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue){
uint32_t result = 0;
loop_while_flag_is(I2C_FLAG_BUSY,1); /*!< While the bus is busy */
I2C_GenerateSTART(I2C1, ENABLE); /* Start the config sequence */
loop_till_event(I2C_EVENT_MASTER_MODE_SELECT); /* Test on EV5 and clear it */
I2C_Send7bitAddress(I2C1, CODEC_ADDRESS, I2C_Direction_Transmitter); /* Transmit the slave address and enable writing operation */
loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); /* Test on EV6 and clear it */
I2C_SendData(I2C1, RegisterAddr); /* Transmit the first address for write operation */
loop_till_event(I2C_EVENT_MASTER_BYTE_TRANSMITTING); /* Test on EV8 and clear it */
I2C_SendData(I2C1, RegisterValue); /* Prepare the register value to be sent */
loop_while_flag_is(I2C_FLAG_BTF, 0); /*!< Wait till all data have been physically transferred on the bus */
I2C_GenerateSTOP(I2C1, ENABLE); /* End the configuration sequence */
result = (Codec_ReadRegister(RegisterAddr) == RegisterValue)? 0:1; /* Verify that the data has been correctly written */
return result; /* Return the verifying value: 0 (Passed) or 1 (Failed) */
}
void micro_App__CMSIS_I2C(){
Resources__ExBoard_init(_, "CMSIS-I2C");
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); /* Enable the I2C1 peripheral clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef
GPIO_InitStructure = {0};
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); /* I2C SCL pin Configuration */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); /* I2C SDA pin Configuration */
/* I2C1 peripheral configuration */
I2C_DeInit(I2C1);
I2C_InitTypeDef
I2C_InitStructure = {0};
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x33;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE); /* Enable the I2C peripheral */
DO__write(PD4->owner, PD4, 0);
volatile int i = 0; for(;i < 10000; i++);
DO__write(PD4->owner, PD4, 1);
Codec_WriteRegister(0x02, 0x01); /* Keep Codec powered OFF */
Codec_WriteRegister(0x04, 0xAF); /* SPK always OFF & HP always ON */
Codec_WriteRegister(0x05, 0x81); /* Clock configuration: Auto detection */
Codec_WriteRegister(0x06, CODEC_STANDARD); /* Set the Slave Mode and the audio Standard */
while(1){}
}