Programación de la comunicación IIC de Blue Bridge Cup integrada
Primero, abrimos el archivo del controlador oficial que contiene el código IIC
La ruta es la siguiente:
Diseño y desarrollo incrustados \ Programa de referencia I2C.
Agregue estos dos proyectos a nuestra plantilla de proyecto.
Luego, abrimos la hoja de datos oficial que nos proporcionó AT24301.
Busque la introducción del bit de dirección y
podrá ver que el bit de dirección viene determinado por el tamaño de la memoria A2 A1 P1 P0 Se decide por R / W,
entonces abrimos el diagrama esquemático que nos dio el funcionario para encontrar el chip al que quiere corresponder el IIC. El
oficial es M24C02MN6 y el nuestro tiene algunos tomas de corriente,
pero no es importante. Podemos suponer que E0 E1 E2 corresponde a A0 A1 A2
debido a estos tres. Los pines están todos conectados a tierra, por lo que introdujimos que estos tres bits son todos bajos,
por lo que podemos determinar los bits de dirección que desear
Si queremos escribir (W),
nuestro bit de dirección es
1 0 1 0 0 0 0 (0)
[Por qué escribir 0, consulte el diagrama de secuencia de lectura y escritura a continuación]
Convertido a hexadecimal es 0xA0
Si queremos leer (R), entonces
1 0 1 0 0 0 0 (1)
[Por qué escribir 1, consulte el diagrama de secuencia de lectura y escritura a continuación]
Convertido a hexadecimal es 0xA1
A continuación, escribiremos uno de nuestros programas de lectura y escritura de IIC basados en el diagrama de entrenamiento.
Se puede ver claramente que la línea horizontal correspondiente arriba de R / W está debajo,
por lo que se infiere que Chu W (escritura) es de nivel bajo.
Entonces no necesitamos prestar atención al nivel alto y bajo del diagrama de tiempo
porque la biblioteca oficial ya ha escrito la función correspondiente.A
lo que debemos prestar atención es al orden en el que usamos las funciones oficiales (solo mire la parte superior del diagrama de tiempo) y ACK
nota: Esto -> DEVIE ADDRESS en realidad corresponde a la los siguientes 8 bytes, que es el bit de dirección del chip de memoria que mencionamos anteriormente. Vea que el frente es 1010 y luego 3 bits inciertos
y un R \ W son todos bits escritos
[ACK significa esperar respuesta del programa]
Mire de izquierda a derecha
-> INICIO
-> DIRECCIÓN DEL DISPOSITIVO
-> ACK
-> WORD ADDRESS
-> ACK
-> DATA
-> ACK
-> STOP
Desde el diagrama de entrenamiento, podemos ver que no solo necesitamos enviar
a la dirección
del componente, necesitamos enviar la dirección donde almacenamos los datos
y los datos que queremos almacenar
Uno de nuestros programas de envío que escribimos sobre esto.
void x24c02_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(info);
I2CWaitAck();
I2CStop();
}
Entonces escribiremos nuestro programa de lectura
Entonces puede verse en este diagrama de tiempo
-> INICIO
-> DIRECCIÓN
DE DISPOSITIVO -> ACK
-> DIRECCIÓN WROD
-> ACK
-> INICIO
-> DIRECCIÓN DEL DISPOSITIVO
-> LEER
-> DATOS
-> NO ACK
-> DETENER
Esta función de lectura usamos el valor de retorno de I2CReceiveByte () para leer el
código fuente del programa de la siguiente manera
uint8_t x24c02_read(uint8_t address)
{
unsigned char val;
//发送芯片的写地址
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return(val);
}
Luego implementamos la función de este programa IIC en la función principal.
Agregamos 1 al número de encendido que se muestra cada vez que encendemos
int main(void)
{
uint8_t temp;
uint8_t string[20];
SysTick_Config(SystemCoreClock/1000); //1msÖжÏÒ»´Î
//LCD¹¤×÷ģʽÅäÖÃ
STM3210B_LCD_Init();
LCD_Clear(White);
LCD_SetTextColor(White);
LCD_SetBackColor(Blue);
LCD_ClearLine(Line0);
LCD_ClearLine(Line1);
LCD_ClearLine(Line2);
LCD_ClearLine(Line3);
LCD_ClearLine(Line4);
LCD_DisplayStringLine(Line1," I2C DEMO ");
LCD_DisplayStringLine(Line3," AT24C02 R/W ");
LCD_SetTextColor(Blue);
LCD_SetBackColor(White);
i2c_init();
temp = IIC_read(0xff);
Delay_Ms(2);
IIC_write(0xff,++temp);
Delay_Ms(2);
sprintf(string,"%s%d","ADDR:0xFF,VAL:",temp);
LCD_DisplayStringLine(Line6,string);
while(1){
}
}
A continuación se muestra el código de I2C.c
/*
³ÌÐò˵Ã÷: CT117EǶÈëʽ¾ºÈü°åGPIOÄ£ÄâI2C×ÜÏßÇý¶¯³ÌÐò
Èí¼þ»·¾³: Keil uVision 4.10
Ó²¼þ»·¾³: CT117EǶÈëʽ¾ºÈü°å
ÈÕ ÆÚ: 2011-8-9
*/
#include "stm32f10x.h"
/** I2C ×ÜÏß½Ó¿Ú */
#define I2C_PORT GPIOB
#define SDA_Pin GPIO_Pin_7
#define SCL_Pin GPIO_Pin_6
#define FAILURE 0
#define SUCCESS 1
//ÅäÖÃSDAÐźÅÏßΪÊäÈëģʽ
void SDA_Input_Mode()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//ÅäÖÃSDAÐźÅÏßΪÊä³öģʽ
void SDA_Output_Mode()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//
void SDA_Output( uint16_t val )
{
if ( val ) {
GPIO_SetBits(I2C_PORT,SDA_Pin);
} else {
GPIO_ResetBits(I2C_PORT,SDA_Pin);
}
}
//
void SCL_Output( uint16_t val )
{
if ( val ) {
GPIO_SetBits(I2C_PORT,SCL_Pin);
} else {
GPIO_ResetBits(I2C_PORT,SCL_Pin);
}
}
//
uint8_t SDA_Input()
{
return GPIO_ReadInputDataBit( I2C_PORT, SDA_Pin);
}
//ÑÓʱ³ÌÐò
void delay1(unsigned int n)
{
unsigned int i;
for ( i=0;i<n;++i);
}
//I2C×ÜÏßÆô¶¯
void I2CStart(void)
{
SDA_Output(1);delay1(500);
SCL_Output(1);delay1(500);
SDA_Output(0);delay1(500);
SCL_Output(0);delay1(500);
}
//I2C×ÜÏßÍ£Ö¹
void I2CStop(void)
{
SCL_Output(0); delay1(500);
SDA_Output(0); delay1(500);
SCL_Output(1); delay1(500);
SDA_Output(1); delay1(500);
}
//µÈ´ýÓ¦´ð
unsigned char I2CWaitAck(void)
{
unsigned short cErrTime = 5;
SDA_Input_Mode();
delay1(500);
SCL_Output(1);delay1(500);
while(SDA_Input())
{
cErrTime--;
delay1(500);
if (0 == cErrTime)
{
SDA_Output_Mode();
I2CStop();
return FAILURE;
}
}
SDA_Output_Mode();
SCL_Output(0);delay1(500);
return SUCCESS;
}
//·¢ËÍÓ¦´ðλ
void I2CSendAck(void)
{
SDA_Output(0);delay1(500);
delay1(500);
SCL_Output(1); delay1(500);
SCL_Output(0); delay1(500);
}
//
void I2CSendNotAck(void)
{
SDA_Output(1);
delay1(500);
SCL_Output(1); delay1(500);
SCL_Output(0); delay1(500);
}
//ͨ¹ýI2C×ÜÏß·¢ËÍÒ»¸ö×Ö½ÚÊý¾Ý
void I2CSendByte(unsigned char cSendByte)
{
unsigned char i = 8;
while (i--)
{
SCL_Output(0);delay1(500);
SDA_Output(cSendByte & 0x80); delay1(500);
cSendByte += cSendByte;
delay1(500);
SCL_Output(1);delay1(500);
}
SCL_Output(0);delay1(500);
}
//´ÓI2C×ÜÏß½ÓÊÕÒ»¸ö×Ö½ÚÊý¾Ý
unsigned char I2CReceiveByte(void)
{
unsigned char i = 8;
unsigned char cR_Byte = 0;
SDA_Input_Mode();
while (i--)
{
cR_Byte += cR_Byte;
SCL_Output(0);delay1(500);
delay1(500);
SCL_Output(1);delay1(500);
cR_Byte |= SDA_Input();
}
SCL_Output(0);delay1(500);
SDA_Output_Mode();
return cR_Byte;
}
//I2C×ÜÏß³õʼ»¯
void i2c_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // **
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//自己写的代码
void IIC_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendAck();
I2CWaitAck();
I2CStop();
}
u8 IIC_read(u8 adress)
{
unsigned char val;
I2CStart();
I2CSendByte(0XA0);
I2CWaitAck();
I2CSendByte(adress);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val=I2CReceiveByte();
I2CWaitAck();
I2CStop();
return val;
}
código i2c.h
#ifndef __I2C_H__
#define __I2C_H__
#include "stm32f10x.h"
void i2c_init(void);
void delay1(unsigned int n);
void I2CStart(void);
void I2CStop(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
unsigned char I2CWaitAck(void);
void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
void IIC_write(unsigned char address,unsigned char info);
u8 IIC_read(u8 adress);
#endif