
WCH사의 작고 저렴한 USB MCU (CH32X035) 를 테스트할 때 아쉬운점은 I2C가 USB 채널과 공용으로 사용하고 있어서 I2C를 소프트웨어로 구형 했어야 했는데 CH32V208은 I2C를 별도로 동작 가능하다.
CH32V208 SSM 보드는 PB6(SCL), PB7(SDA) 핀이 할당되어 있다.

I2C 초기화 함수를 작성하자. 기본 제공 예제은 I2C핀을 리맵해서 사용하기 때문에 리맵을 사용하지 않도록 수정이 필요하다.
void IIC_Init(u32 bound, u16 address)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
I2C_InitTypeDef I2C_InitTSturcture={0};
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE );
//GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure );
I2C_InitTSturcture.I2C_ClockSpeed = bound;
I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_16_9;
I2C_InitTSturcture.I2C_OwnAddress1 = address;
I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init( I2C1, &I2C_InitTSturcture );
I2C_Cmd( I2C1, ENABLE );
#if (I2C_MODE == HOST_MODE)
I2C_AcknowledgeConfig( I2C1, ENABLE );
#endif
}
I2C 전송 함수 작성
STM32와 유사한 코드 구조이기 때문에 기존에 사용하던 STM32의 I2C 제어 코드와 동일하게 작성 해 두면 기존에 작성해 두었던 I2C 관련 코드를 그대로 사용할수 있을것 같다.
먼저 HAL_I2C_Master_Transmit 함수를 포팅 하자.
#define _I2C_DELAY_TIME 1000
#define I2C_HANLDLE hi2c1
#define PCF_8574_ADDR (0x20)
int HAL_I2C_Master_Transmit(I2C_TypeDef *I2Cx, unsigned char Address, unsigned char *TxData, unsigned int _Size, unsigned int DelayTime)
{
while( I2C_GetFlagStatus( I2Cx, I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( I2Cx, ENABLE );
while( !I2C_CheckEvent( I2Cx, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2Cx, Address<<1, I2C_Direction_Transmitter );
while( !I2C_CheckEvent( I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
for( int i=0; i< _Size;i++ )
{
if( I2C_GetFlagStatus( I2Cx, I2C_FLAG_TXE ) != RESET )
{
Delay_Ms(DelayTime);
I2C_SendData( I2Cx, TxData[i] );
}
}
while( !I2C_CheckEvent( I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_GenerateSTOP( I2Cx, ENABLE );
}
void write8(uint8_t Address, uint8_t Value)
{
HAL_I2C_Master_Transmit(I2C1, Address, &Value, 1, _I2C_DELAY_TIME);
}
I2C를 가장 간단하게 테스트 할 수 있는 보드로 SSM Type의 PCF8574 보드를 이용하여 GPIO 핀을 확장하는 예제를 구동해 보자.
int main(void)
{
Delay_Init();
USART_Printf_Init( 115200 );
printf( "SystemClk:%d\r\n", SystemCoreClock );
printf("IIC Host mode\r\n");
IIC_Init( 100000, 0);
while(1)
{
write8(PCF_8574_ADDR, 0xFF);
Delay_Ms(100);
write8(PCF_8574_ADDR, 0x00);
Delay_Ms(100);
}
}반응형