24c04硬件地址位_STM32硬件IC主传从收

研究了很久STM32的硬件IIC,网上很多人都说硬件IIC可以能哪里不好,但是还是参考官方列程写了一个自发自收的。。新人写的不好勿喷,全部代码如下:

/*----------------------------------------------------------------------------------------------------

名称: I2C 测试 24C02 测试

编写: mingzhang.zhao

内容:测试 stm32f103vct6 的硬件 I2C 实现中断收发数据

注意事项:

1.USART1: PA9 为 TX, PA10 为 RX

I2C1: PB6 为 SCL, PB7 为 SDA

I2C2: PB10 为 SCL, PB11 为 SDA

—————————————————————————————————————*/

#include "stm32f10x.h"

#include "stdio.h"

#define PRINTF_ON 1

void RCC_Configuration(void);void GPIO_Configuration(void);

void USART_Configuration(void);

void I2C_Configuration(void);

void NVIC_Configuration(void);

void Delay(__IO uint32_t t);

u8 I2C1_ADDRESS = 0x30; //7 位 I2C 地址

u8 I2C2_ADDRESS = 0x31;

#define Size 4

vu8 I2C1_Buffer_Tx[Size] = {1,2,3,4};

vu8 I2C2_Buffer_Rx[Size] = {0};

u32 BufferSize = Size ;

extern u32 BufferSize ;

extern u8 I2C1_ADDRESS ;

extern u8 I2C2_ADDRESS ;

extern vu8 I2C1_Buffer_Tx[];

extern vu8 I2C2_Buffer_Rx[];

vu32 Tx_Counter = 0;

vu32 Rx_Counter = 0;

vu32 show_counter1 = 0;

vu32 show_counter2 = 0;

// I2C1 作为主机,用于中断接收从机数据

void I2C1_EV_IRQHandler(void)

{

show_counter1++;

if(show_counter1 > 1000000)

{

show_counter1 = 0;

printf("rn The I2C1 LastEvent is %x rn", I2C_GetLastEvent(I2C1)); //中断发送

}

switch(I2C_GetLastEvent(I2C1))

{

case I2C_EVENT_MASTER_MODE_SELECT: // EV9中断 已发送启始条件

{

// 七位地址发送

I2C_Send7bitAddress(I2C1, I2C2_ADDRESS, I2C_Direction_Receiver);//I2C1,I2C2设备地址,器件地址0x01

printf("rn The I2C1 is ready rn");

break;

}

case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: // EV6中断 已发送从机地址

{

printf("rn The slave address is %x rn", I2C_ReceiveData(I2C1)); //返回I2C1最近接受的数据

break;

}

case (I2C_EVENT_MASTER_BYTE_RECEIVED | (I2C_FLAG_BTF & 0x0f)): // EV7中断 第一个数据已接收

{

// 要接收最后一个字节前先关总线,不然总线锁死

I2C_GenerateSTOP(I2C1,ENABLE); //I2C1传输STOP条件

printf("rn The I2C1 has received data2 %x rn", I2C_ReceiveData(I2C1));

printf("rn The I2C1 is finish rn");

break;

}

case 0x40:

{

// 接收了两个同样的数据,没有这个释放不了 RXNE

I2C_ReceiveData(I2C1);

}

default: {break;}

}

}

// I2C2 用于从机发送数据到主机

void I2C2_EV_IRQHandler(void) //输入事件中断

{

show_counter2++;

if(show_counter2 > 100000)

{

show_counter2 = 0;

printf("rn The I2C2 LastEvent is %x rn", I2C_GetLastEvent(I2C2)); //I2C2返回最近一次事件

}

switch(I2C_GetLastEvent(I2C2)) //检测到输入

{

// 收到匹配的地址数据

case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1中断

{

printf("rn The I2C2 is ready rn");

I2C_GenerateSTOP(I2C2, DISABLE); //I2C2使能STOP条件

break;

}

case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: // EV8中断

{

printf("rn The I2C2 transmits is transmitting rn");

I2C_SendData(I2C2, 0xb6 + Rx_Counter); //发送数据

break;

}

//发送数据,要发送,不然锁死,不过 master 没收到

case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3中断

{

printf("rn The I2C2 transmits one byte rn");

I2C_SendData(I2C2, 0xb6 + (Rx_Counter++)); //发送数据

break;

}

case I2C_EVENT_SLAVE_STOP_DETECTED: // EV4中断 收到结束条件

{

printf("rn The I2C2 is finish rn");

I2C_ClearFlag(I2C2,I2C_FLAG_STOPF); //消除I2C2的标志位

I2C_GenerateSTOP(I2C2, ENABLE); //I2C2使能STOP条件

break;

}

default: {break;}

}

}

int main(void)

{

RCC_Configuration();

GPIO_Configuration();

USART_Configuration();

I2C_Configuration();

NVIC_Configuration();

I2C_GenerateSTART(I2C1,ENABLE);

while(1)

{

Delay(1000);

I2C_GenerateSTART(I2C1,ENABLE); //使能I2C1 循环读取数据

}

}

// 初始化和配置相关

void I2C_Configuration(void)

{

I2C_InitTypeDef I2C_InitStructure; //I2C结构定义

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置为I2C模式

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //I2C快速模式2

I2C_InitStructure.I2C_OwnAddress1 = I2C1_ADDRESS; //设置I2C1设备自身地址

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能应答

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //设置应答7位地址

I2C_InitStructure.I2C_ClockSpeed = 200000; //设置时钟频率

I2C_Init(I2C1,&I2C_InitStructure); //初始化I2C1

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置为I2C模式

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //I2C快速模式

I2C_InitStructure.I2C_OwnAddress1 = I2C2_ADDRESS; //设置I2C2的地址

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能应答

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //设置应答7位地址

I2C_InitStructure.I2C_ClockSpeed = 200000; //设置时钟频率

I2C_Init(I2C2,&I2C_InitStructure); //初始化I2C2

I2C_ITConfig(I2C1,I2C_IT_EVT|I2C_IT_BUF,ENABLE); //使能I2C1缓存、事件中断屏蔽

I2C_ITConfig(I2C2,I2C_IT_EVT|I2C_IT_BUF,ENABLE); //使能I2C2缓存、事件中断屏蔽

I2C_Cmd(I2C1,ENABLE); //使能I2C1外设

I2C_Cmd(I2C2,ENABLE); //使能I2C2外设

}

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure; //中断优先级类型结构定义

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置先占优先级1位,从优先级3位

NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn; //设置I2C1事件中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //设置先占优先级1位,从占优先级3位

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从占优先级0位,占优先级4位

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure); //中断初始化

NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn; //设置I2C2事件中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0位

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从占优先级0位

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure); //中断初始化

}

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

//初始化 I2C1

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最高输出速率为50MHz

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //选中引脚Pin6,Pin7

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //设置为复用开漏输出

GPIO_Init(GPIOB , &GPIO_InitStructure); //初始化GPIOB

//初始化 I2C2

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; //选中引脚Pin10,Pin11

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最高输出速率为50MHz

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //设置为复用开漏输出

GPIO_Init(GPIOB , &GPIO_InitStructure); //初始化GPIOB

//初始化 USART1

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //选中RX端口

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

GPIO_Init(GPIOA , &GPIO_InitStructure); //初始化GPIOA

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选中TX端口

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入

GPIO_Init(GPIOA , &GPIO_InitStructure); //初始化GPIOA

}

void RCC_Configuration(void)

{

/* 定义枚举类型变量 HSEStartUpStatus */

ErrorStatus HSEStartUpStatus;

/* 复位系统时钟设置*/

RCC_DeInit();

/* 开启 HSE*/

RCC_HSEConfig(RCC_HSE_ON);

/* 等待 HSE 起振并稳定*/

HSEStartUpStatus = RCC_WaitForHSEStartUp();

/* 判断 HSE 起是否振成功,是则进入 if()内部 */

if(HSEStartUpStatus == SUCCESS)

{

/* 选择 HCLK(AHB)时钟源为 SYSCLK 1 分频 */

RCC_HCLKConfig(RCC_SYSCLK_Div1);

/* 选择 PCLK2 时钟源为 HCLK(AHB) 1 分频 */

RCC_PCLK2Config(RCC_HCLK_Div1);

/* 选择 PCLK1 时钟源为 HCLK(AHB) 2 分频 */RCC_PCLK1Config(RCC_HCLK_Div2);

/* 设置 FLASH 延时周期数为 2 */

FLASH_SetLatency(FLASH_Latency_2);

/* 使能 FLASH 预取缓存 */

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

/* 选择锁相环(PLL)时钟源为 HSE 1 分频, 倍频数为 9,则 PLL 输出频率为 8MHz

* 9 = 72MHz */

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

/* 使能 PLL */

RCC_PLLCmd(ENABLE);

/* 等待 PLL 输出稳定 */

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

/* 选择 SYSCLK 时钟源为 PLL */

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

/* 等待 PLL 成为 SYSCLK 时钟源 */

while(RCC_GetSYSCLKSource() != 0x08);

}

/* 打开 APB2 总线上的 GPIOA 时钟*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1, ENABLE);

//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1|RCC_APB1Periph_I2C2,ENABLE);

//RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP|RCC_APB1Periph_WWDG|RCC_APB1Periph_SPI2, ENABLE);

}

void USART_Configuration(void)

{

USART_InitTypeDef USART_InitStructure; //定义结构体

USART_ClockInitTypeDef USART_ClockInitStructure; //定义串口时钟结构

USART_ClockInitStructure.USART_Clock = USART_Clock_Disable; //时钟低电平活动

USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low; //时钟低电平

USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge; //时钟第二个边沿进行数据捕获

USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable; //最后一位数据的时钟脉冲不从SCLK输出

USART_ClockInit(USART1 , &USART_ClockInitStructure); //初始串口时钟

USART_InitStructure.USART_BaudRate = 9600; //波特率9600

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据

USART_InitStructure.USART_StopBits = USART_StopBits_1; //8位后传输1个停止位

USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶失能

USART_InitStructure.USART_HardwareFlowControl =

USART_HardwareFlowControl_None; //硬件流控制失能

USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //使能发送和接收

USART_Init(USART1,&USART_InitStructure); //初始化串口

USART_Cmd(USART1,ENABLE); //使能串口

}

void Delay(__IO uint32_t t) //延迟。。

{

while(t--);

}

#if PRINTF_ON

int fputc(int ch,FILE *f) //重定义fputc函数

{

USART_SendData(USART1,(u8) ch);

while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);

return ch;

}

#endif

注释非常详细了,留个学习纪念-----^_^

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值