STM32 마이크로컨트롤러 초보자 4-IIC 통신(소프트웨어 시뮬레이션)

IIC ( Inter-Integrated Circuit )는 I2C("I Fang C"를 읽는 데 사용됨)라고도 하며 IIC 버스의 약자이며 중국어 이름은 집적 회로 버스이며 멀티 마스터를 사용하는 직렬 통신 버스입니다. - 필립스 가 개발한 슬레이브 아키텍처 1980년대에 마더보드 , 임베디드 시스템 또는 휴대폰을 저속 주변 장치에 연결할 수 있도록 개발되었습니다. IC 간의 근거리 데이터 전송에 적합합니다.

초기 IIC 통신 속도는 100Kbps(12.5KB/s)에 불과했고 이후 400Kbps(50KB/s)로 발전한 후 1Mbps, 3.4Mbps(고속 모드)로 발전했다. 속도가 빠를수록 통신 장비에 대한 요구 사항이 높아지므로 많은 IIC 통신 장비가 고속 모드를 지원하지 않습니다.

IIC는 단일 칩 마이크로컴퓨터에서 가장 일반적으로 사용되는 통신 방법 중 하나이며, 단일 칩 마이크로컴퓨터가 EEPROM 메모리 칩을 확장해야 하는 경우 IIC 통신을 사용하여 EEPROM 데이터를 읽고 씁니다.

또한 많은 센서(예: 온도 및 습도 센서, 가속도 센서 등), 주변 장치(예: OLED 화면, LCD 디스플레이 패널 등)도 데이터 전송을 위해 IIC 및 마이크로 컨트롤러를 사용합니다.

따라서 IIC는 마이크로컨트롤러에서 없어서는 안 될 학습 콘텐츠입니다.

이 기사의 제목은 특히 "소프트웨어 시뮬레이션" IIC 통신을 강조합니다. 하드웨어 IIC 통신도 포함되어 있습니까? 예.

하드웨어 IIC : 우리는 STM32가 하드웨어 수준의 IIC 통신을 포함하여 풍부한 주변 장치를 가지고 있다는 것을 알고 있습니다. 준비된 공식 라이브러리 기능을 통해 IIC 통신을 직접 구현할 수 있습니다.

IIC의 소프트웨어 시뮬레이션은 내부 IIC 통신 모듈을 사용하지 않으며 공식 라이브러리 기능을 사용하지 않으며 소프트웨어 시뮬레이션에 전적으로 의존하여 IIC의 통신 방법을 실현합니다.

STM32의 하드웨어 IIC에는 응답 신호가 고정되는 문제가 있으므로 많은 개발자는 소프트웨어를 사용하여 IIC 통신을 시뮬레이션하는 것을 선호합니다. 또한 소프트웨어 시뮬레이션 IIC는 다른 장치로의 포팅이 용이하고, 원하는 기능을 자체적으로 캡슐화할 수 있어 하드웨어 IIC보다 유연하다는 장점이 있습니다.

그렇다면 IIC의 소프트웨어 시뮬레이션은 어떻게 실현되는 것일까요?

먼저 어떤 유선 통신 방식이든 통신선을 통해 고레벨과 저레벨 신호를 전송함으로써 구현된다는 점을 알아두세요. 데이터의 최소 단위는 비트이며, 1비트는 0 또는 1을 나타낼 수 있으며, 하이 레벨과 로우 레벨은 이 두 가지 상태를 나타낼 수 있습니다. 끊임없이 변화하는 높은 수준과 낮은 수준은 변화하는 0과 1을 나타낼 수 있으며 이들을 연결하여 일련의 데이터를 형성합니다.

따라서 이론적으로 높고 낮은 수준의 신호를 생성할 수 있는 한 통신에 사용할 수 있습니다. 단일 칩 마이크로컴퓨터의 IO 포트는 고레벨과 저레벨을 출력할 수 없으므로 프로그램을 통해 특정 규칙에 따라 IO 포트가 고레벨과 저레벨을 출력하도록 하는 한 통신 을 실현할 수 있습니다. 이 통신 방법을 소프트웨어 시뮬레이션 통신 이라고 합니다 . 위에서 언급한 법칙은 통신 프로토콜입니다.

데이터 송신자가 보낸 데이터가 수신자에게 인식되기 위해서는 특정한 프로토콜이 합의되어야 하고, 그 합의에 따라 양 당사자가 데이터를 주고 받는데, 이러한 프로토콜을 통신 프로토콜이라고 합니다 .

일반적으로 통신 수단이란 물리적 인터페이스통신 프로토콜을 모두 포함합니다 .

물리적인 인터페이스: 일반 용어로는 여러 개의 통신 라인이 필요하며, 각 통신 라인의 정의 및 연결 방법, 예를 들어 IIC는 SCL과 SDA의 두 가지 통신 라인이 필요하며 하나의 라인 없이는 통신이 불가능합니다.

통신 프로토콜: 다양한 신호 및 데이터 프레임 형식의 정의를 포함합니다. 송신단은 보낼 데이터를 프로토콜에 따라 재정렬한 후 내보내고, 수신단은 수신한 데이터를 프로토콜에 따라 분석하여 정확한 데이터를 얻는다. 수신 측은 프로토콜에 따라 전송되지 않은 데이터를 유효하지 않은 데이터로 간주하고 처리하지 않습니다.

이것이 서로 다른 통신 방식을 가진 장치들이 서로 통신할 수 없는 이유입니다. 서로 다른 통신 방법은 서로 다른 통신 프로토콜을 갖지만 동일한 통신 인터페이스를 사용할 수 있습니다. 예를 들어, RS485와 RS422의 물리적 인터페이스는 동일하지만 내부에서 사용되는 통신 프로토콜이 다를 수 있으며, RS232의 물리적 인터페이스는 앞의 둘과 다릅니다.

따라서 통신을 설정하기 위한 조건은 물리적 인터페이스, 통신 프로토콜입니다.

이제 IIC 통신으로 돌아갑니다.

IIC 물리적 인터페이스 : IIC 직렬 버스에는 두 개의 신호 라인이 있습니다. 하나는 양방향 데이터 라인 SDA이고 다른 하나는 클록 라인 SCL입니다. I2C 버스 장치에 연결된 모든 직렬 데이터 SDA는 버스의 SDA에 연결되고 각 장치의 클록 라인 SCL은 버스의 SCL에 연결되며 이는 다중 마스터 및 다중 슬레이브 버스에 속합니다. 마스터는 한 번에 하나의 슬레이브와만 통신할 수 있으며 여러 슬레이브와 데이터를 전송하려면 폴링을 사용해야 합니다. 일반적으로 외부 풀업 저항은 데이터 전송이 없을 때 버스가 유휴 상태에 있도록 SDA 및 SCL에 연결됩니다. 그러나 연결하지 않는 것도 가능하며 STM32의 온칩 풀업 저항을 사용할 수 있습니다.

이 두 라인 중 SCL은 클록 신호를 동기화하는 데 사용되는 클록 라인이고 SDA는 데이터를 전송하는 데 사용되는 데이터 라인입니다.

하드웨어 IIC인 경우 이 두 라인을 STM32의 특정 핀에 연결해야 합니다. STM32F03C8T6을 예로 들면 IIC2의 SCL은 PB10이고 SDA는 PB11입니다. 그러면 슬레이브의 SCL만 연결할 수 있습니다. PB10에, SDA는 PB11에만 연결할 수 있습니다.

 그러나 IIC를 시뮬레이트하는 소프트웨어에는 제한이 없으며 두 개의 IO 포트를 각각 SCL 및 SDA로 정의할 수 있습니다.

IIC 통신 프로토콜 : IIC 통신 프로토콜은 비교적 간단하며 주로 시작 신호, 데이터 프레임, 응답 신호 및 정지 신호로 구성됩니다.

보내는 데이터의 형식은 다음과 같습니다.

 데이터를 전송하기 전에 STM32는 먼저 시작 신호를 생성하고 신호를 받은 후 각 슬레이브는 마스터가 데이터를 보낼 것임을 알고 데이터를 받을 준비가 됩니다. 그런 다음 MCU는 일련의 데이터(8비트 이진수)를 전송하기 시작하고 응답을 기다리는 상태로 들어가며 이 데이터 문자열을 수신한 후 슬레이브는 MCU에 응답 신호를 반환하여 MCU에 알립니다. 방금 데이터를 받았습니다. 응답 신호를 수신한 후 단일 칩 마이크로컴퓨터는 다음 데이터 프레임을 계속 전송한 다음 슬레이브에서 응답 신호를 수신할 때까지 응답 대기 상태에 들어갑니다.

모든 데이터가 전송될 때까지 계속 반복합니다. 그런 다음 마이크로 컨트롤러는 내 데이터가 전송되었으며 휴식을 취할 수 있음을 슬레이브에 알리기 위해 중지 신호를 보냅니다. 슬레이브가 중지 신호를 수신한 후 다시 시작 신호를 수신하지 않는 한 데이터 수신을 중지합니다. 물론 슬레이브와 통신이 성립되면 데이터를 보낸 후 정지 신호를 보내지 않을 수도 있으므로 통신은 유지되고 다음에 데이터를 보낼 때 다시 시작 신호를 보낼 필요는 없다. .

하지만 여러 명의 슬레이브가 있는 경우 정지 신호를 보내지 않으면 항상 버스가 점유되어 다른 슬레이브가 마이크로컨트롤러와 통신할 수 없게 됩니다(여자 친구와 전화로 통화한 후 시간에 끊기는 것과 같습니다). , 그렇지 않으면 당신의 좋은 형제는 당신을 부를 수 없습니다). 따라서 더 많은 슬레이브에서 내리고 데이터를 보낸 후 제 시간에 중지 신호를 보냅니다.

다음으로 각 신호와 이를 프로그램에 구현하는 방법에 대해 자세히 설명한다.

먼저 SCL과 SDA의 핀을 정의하고 두 핀을 high와 low로 설정하는 기능을 정의합니다.

PA1을 SCL로, PA2를 SDA로 설정합니다.

#define IIC_SCL_H() GPIO_SetBits(GPIOA,GPIO_Pin_1)	    //定义SCL置高为PA1置位		
#define IIC_SCL_L() GPIO_ResetBits(GPIOA,GPIO_Pin_1)    //定义SCL置低为PA1复位				

#define IIC_SDA_H() GPIO_SetBits(GPIOA,GPIO_Pin_2)		//定义SDA置高为PA2置位			
#define IIC_SDA_L() GPIO_ResetBits(GPIOA,GPIO_Pin_2)	//定义SDA置低为PA2复位		

지연 기능:

void Delay_us(int Time)
{
	int i=0;
	while(Time--)
	{
		i=8;
		while(i--);
	}
	return;
}

SDA는 입력 모드와 출력 모드 사이를 전환해야 하므로(PA2는 응답 대기 시 입력 모드로 전환해야 함) 이 두 가지 기능도 정의해야 합니다. 출력 모드는 푸시 풀 출력이 될 수 있고 입력 모드는 풀업 입력 모드가 될 수 있습니다(버스가 외부 풀업 저항과 연결되어 있으면 플로팅 입력도 사용할 수 있음).

STM32GPIO 모드에 대해서는 STM32_GPIO 상세 설명 문서를 참조하십시오.

void SDA_OUT(void)    //SDA输出模式
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;        //推挽输出模式
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}


void SDA_IN(void)       //SDA输入模式
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;			//上拉输入模式
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

시작 신호:

시작 신호를 보내기 전에 IIC 버스가 유휴 상태인지 확인해야 합니다. 버스가 사용 중이면 시작 신호가 확실히 작동하지 않습니다. 먼저 IIC의 유휴 상태에 대해 이야기하십시오.

IIC의 유휴 상태에서 SCL과 SDA는 모두 높은 수준입니다. 이 상태에서는 버스가 해제되고(MCU 슬레이브 중 어느 것도 버스를 풀다운하지 않음) 데이터 전송이 없습니다.

시작 신호는 SCL이 하이 레벨이고 SDA가 하강 에지를 가질 때입니다. 아래 그림의 점선 상자에 표시된 것처럼.

그림에서 레벨 변화의 기울기는 이해를 돕기 위한 것이지만 실제 기울기는 명확하지 않습니다.

프로그램은 다음과 같이 구현됩니다.


void IIC_Start(void)
{
    SDA_OUT();		//SDA切换至输出模式
    IIC_SDA_H();		//SDA置高
    IIC_SCL_H();		//SCL置高
    Delay_us(1);
    IIC_SDA_L();		//SDA置低
    Delay_us(1);
}

프로그램에서 SDA와 SCL이 모두 높게 설정된 후 1us 지연 후 SDA를 낮게 설정하고 높게 설정하면 짧은 지연이 있음) 동시에 IIC 슬레이브가 버스 레벨 상태를 수집할 수 있는 충분한 시간을 제공합니다. . 일부 저속 IIC 장치와 마찬가지로 느린 속도로 레벨 상태를 수집하므로 호스트는 데이터 전송 속도를 늦춰야 합니다. 즉, 레벨이 변경될 때 지연 시간을 늘려야 합니다. 고속 IIC 장치의 경우 지연을 줄일 수 있습니다. 이것은 또한 IIC 통신 속도를 제한하는 요소 중 하나입니다. 

정지 신호:

중지 신호는 SCL이 하이 레벨에 있고 SDA에 상승 에지가 있다는 것입니다. 아래 그림의 점선 상자에 표시된 것처럼.

 정지 신호 이후 SDA와 SCL 모두 하이 레벨 상태에 있으며 이는 버스의 유휴 상태임을 알 수 있습니다.

프로그램을 사용하여 다음과 같이 정지 신호를 구현하십시오.

void IIC_Stop(void)
{
    IIC_SCL_H();		//SCL置高
    IIC_SDA_L();		//SDA置低
    Delay_us(1);
    IIC_SDA_H();		//SDA置高
    Delay_us(1);
}

데이터 프레임:

데이터 프레임은 데이터 전송의 최소 단위입니다.

각 데이터 프레임은 8비트 이진수에 해당하는 1KB의 데이터, 즉 8비트를 전달하며 여기서는 데이터 문자열이라고 합니다.

IIC에서는 상위 바이트가 먼저 전송된 다음 하위 바이트가 전송됩니다. 예를 들어 11001010이라는 데이터가 있다면 데이터 문자열의 IIC는 1-1-0-0-1-0-1-0이고 데이터 전송 순서도 위의 배열 순서에 따른다.

IIC의 동의서에는 SCL이 낮은 수준일 때 SDA가 상태를 변경할 수 있도록 허용되고 SCL이 높은 수준일 때 SDA 상태를 읽도록 규정되어 있습니다.

평신도의 관점에서: SCL이 높은 수준일 때 IIC 버스의 장치는 SDA의 상태를 읽고 SCL이 낮은 수준일 때는 절대 읽지 않습니다. 이 규정은 IIC 버스의 장치를 타이밍 동기화 상태로 유지하기 위한 것입니다.

따라서 데이터 문자열의 타이밍은 다음과 같습니다. SCL은 로우로 설정 - 전송할 데이터 비트가 0 또는 1인지 여부에 따라 SDA를 로우 또는 하이로 설정 - SCL은 하이로 설정 - 지연 - SCL은 로우로 설정 - 전송할 데이터 비트에 따라 SDA 0이냐 1이냐 로우냐 하이냐... 이 사이클을 8번 반복하면 8비트 데이터의 전송이 완료된다.

이제 8비트 이진수 11001010을 전송해야 한다고 가정하면 레벨 변경은 다음과 같아야 합니다.

프로그램은 다음과 같이 구현됩니다.

void IIC_WriteByte(u8 data)			//发送一个数据串,data为要发送的数据
{
    u8 i;
    SDA_OUT();			//SDA设置为输出模式
    for(i=0;i<8;i++)				//循环发送,每次循环发送1bit,循环8次就是1Byte
    {
        IIC_SCL_L();				//SCL置低
        if(data & 0x80)     //如果Data的第八位是高电平
            IIC_SDA_H();		//SDA置高
        else
            IIC_SDA_L();		//SDA置低
        IIC_SCL_H();				//SCL置高
        Delay_us(1);				//延时
        data<<=1;						//data左移一位
    }
}

응답 신호

응답 신호는 상대방이 데이터를 수신했음을 확인하는 데 사용되는 신호입니다. 완전한 데이터 프레임은 데이터 문자열과 응답 신호로 구성됩니다.

데이터 문자열이 전송된 후 SCL을 낮게 설정하고 SDA를 높게 설정한 다음 STM32는 SDA의 IO 포트를 입력 모드로 전환합니다(이전 SDA 하이 레벨은 입력 모드로 전환한 후 버스가 자동으로 변경되기 때문에 생략할 수 있음). 높은 수준) SCL을 높은 수준으로 설정합니다. 그런 다음 지연을 기다리십시오. 슬레이브가 방금 전송된 데이터를 수신하면 SDA를 로우로 끌어올릴 것이며 이 로우 레벨이 응답 신호입니다.

이때 STM32는 입력 모드에 있기 때문에 응답 신호를 수신하고 마지막 데이터 전송이 성공한 것으로 간주하고 출력 모드로 다시 전환하거나 다음 프레임의 데이터 전송을 계속하거나 정지 신호를 보냅니다. 응답 신호가 수신되지 않으면 데이터 전송이 실패한 것으로 간주하고 이전 데이터를 다시 보내거나 정지 신호를 직접 보낼 수 있습니다.

그런 다음 데이터 프레임은 응답 신호가 다음과 같음을 나타냅니다.

다음과 같이 프로그램에서 구현됩니다.

u8 IIC_Wait_Ask(void)
{
    int count=0;        
    IIC_SCL_L();		//SCL置低
    Delay_us(1);        //延时
    IIC_SDA_H();        //SDA置高
	SDA_IN();           //SDA切换成输入模式
    IIC_SCL_H();        //SCL置高
    Delay_us(1);        //延时,等待从机发出应答信号
    while(Read_IIC_SDA)    //如果SDA为低电平
    {
        count++;            //开始计数
        if(count>250)       //计数超过250,则认为数据发送失败,从机无响应
        {
            IIC_Stop();			//发出停止信号	
            return 1;           //函数返回1
        }   
    }
    IIC_SCL_L();           //如果SDA为高电平,则认为收到应答,SCL置低
    Delay_us(1);
    return 0;              //函数返回0
}

IIC 데이터 전송은 위에서 언급한 신호와 데이터 프레임을 기반으로 하며 프레임 단위로 데이터를 전송하기 위해 지속적으로 순환합니다.

이 글은 단순히 IIC의 타이밍과 각 신호 및 데이터 프레임의 프로그램 구현에 대해서만 이야기하고 IIC의 실제 적용은 슬레이브의 레지스터 주소와 명령과도 관련이 있습니다.다음 글(OLED 화면을 구동하는 IIC 통신)에서는 IIC를 통한 STM32와 OLED 화면 간의 데이터 전송을 설명하기 위해 OLED 화면에 표시된 "Hello world"를 예로 들어 보겠습니다 .


이 글은 순전히 개인적인 이해이므로 오류가 있는 경우 수정해 주시기 바랍니다.

이 글이 유익하셨다면 손가락 꾸욱~

Supongo que te gusta

Origin blog.csdn.net/qq_55203246/article/details/123944252
Recomendado
Clasificación