完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
(9)Proteus 8.9上的STM32仿真系列(HAL/CubeMaxIDE)—IIC/I2C实验
实验设计: Proteus上的stm32硬件IIC测试失败,本处采用模拟IIC。控制PCF8574电平,并读取其状态从串口1输出。 一、Proteus原理图(芯片stm32f103r6tx) 1.可以不放逻辑分析仪,COMPIM点开波特率设置为9600。 二、CubemaxIDE配置 1.时钟和第一节相同,直接HCLK 8Mhz。 2.使能uart1,设置9600波特率 3.配置PB0,PB1,后面会重新设置输入输出模式,这里简单打开就好。 4.generate code,需要添加6个文件,delay.c/delay.h如上一节,需新添加Soft_IIC.c/Soft_IIC.h和PCF8574.C/PCF8574.h。后两个文件源代码如下。 目录结构: Soft_IIC.h #ifndef __SOFT_IIC_H #define __SOFT_IIC_H #include "delay.h" /* 高低电平 */ #define HIGH 1 #define LOW 0 /* IO方向设置 */ #define SDA_IN() {GPIOB->CRL&=~(15<<(0*2));GPIOB->CRL|=4<<(0*2);} //PB0浮空输入模式 #define SDA_OUT() {GPIOB->CRL&=~(3<<(0*2));GPIOB->CRL|=1<<(0*2);} //PB0输出模式10Mhz /* IO操作 */ #define IIC_SCL(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET)) //SCL #define IIC_SDA(n) (n?HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET)) //SDA #define READ_SDA HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) //输入SDA /* IIC所有操作函数 */ void IIC_Init(void); //IIC初始化 void IIC_Start(void); //产生IIC起始信号 void IIC_Stop(void); //产生IIC停止信号 uint8_t IIC_Wait_Ack(void); //等待ACK信号到来 void IIC_Ack(void); //产生ACK应答 void IIC_NAck(void); //不产生ACK应答 void IIC_Send_Byte(uint8_t txd); //IIC发送一个字节 uint8_t IIC_Read_Byte(unsigned char ack); //IIC读取一个字节 #endif Soft_IIC.c #include "Soft_IIC.h" /*************************************************************** @Function void IIC_Init(void) @Description IIC初始化 @Input void @Return void ***************************************************************/ void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOB时钟 /* PB0,1初始化设置 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); IIC_SDA(HIGH); IIC_SCL(HIGH); } /*************************************************************** @Function void IIC_Start(void) @Description 产生IIC起始信号 SCL : HIGH SDA : HIGH -> LOW @Input void @Return void ***************************************************************/ void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA(HIGH); IIC_SCL(HIGH); delay_us(4); IIC_SDA(LOW); //START : when CLK is high,DATA change form high to low delay_us(4); IIC_SCL(LOW); //钳住I2C总线,准备发送或接收数据 } /*************************************************************** @Function void IIC_Stop(void) @Description 产生IIC停止信号 SCL : HIGH SDA : LOW -> HIGH @Input void @Return void ***************************************************************/ void IIC_Stop(void) { SDA_OUT(); //sda线输出 IIC_SDA(LOW); IIC_SCL(HIGH); delay_us(4); IIC_SDA(HIGH); //STOP : when CLK is high,DATA change form low to high delay_us(4); } /*************************************************************** @Function uint8_t IIC_Wait_Ack(void) @Description 等待ACK信号到来 @Input void @Return 1 : 接收应答失败 0 : 接收应答成功 ***************************************************************/ uint8_t IIC_Wait_Ack(void) { uint8_t ucErrTime = 0; SDA_IN(); //SDA设置为输入 IIC_SDA(HIGH);delay_us(1); IIC_SCL(HIGH);delay_us(1); while (READ_SDA) { ucErrTime++; if (ucErrTime > 250) { IIC_Stop(); return 1; } } IIC_SCL(LOW); //时钟输出0 return 0; } /*************************************************************** @Function void IIC_Ack(void) @Description 产生ACK应答 @Input void @Return void ***************************************************************/ void IIC_Ack(void) { SDA_OUT(); //sda线输出 IIC_SCL(LOW); IIC_SDA(LOW); delay_us(2); IIC_SCL(HIGH); delay_us(2); IIC_SCL(LOW); } /*************************************************************** @Function void IIC_NAck(void) @Description 不产生ACK应答 @Input void @Return void ***************************************************************/ void IIC_NAck(void) { SDA_OUT(); //sda线输出 IIC_SCL(LOW); IIC_SDA(HIGH); delay_us(2); IIC_SCL(HIGH); delay_us(2); IIC_SCL(LOW); } /*************************************************************** @Function void IIC_Send_Byte(uint8_t txd) @Description IIC发送一个字节 @Input txd : 发送数据 @Return void ***************************************************************/ void IIC_Send_Byte(uint8_t txd) { uint8_t t; SDA_OUT(); //sda线输出 IIC_SCL(LOW); //拉低时钟开始数据传输 for (t = 0; t < 8; t++) { IIC_SDA((txd & 0x80) >> 7); txd <<= 1; delay_us(2); IIC_SCL(HIGH); delay_us(2); IIC_SCL(LOW); delay_us(2); } } /*************************************************************** @Function uint8_t IIC_Read_Byte(unsigned char ack) @Description 读1个字节,ack=1时,发送ACK,ack=0,发送nACK @Input ack @Return 所读数据 ***************************************************************/ uint8_t IIC_Read_Byte(unsigned char ack) { unsigned char i, receive = 0; SDA_IN(); //SDA设置为输入 for (i = 0; i < 8; i++) { IIC_SCL(LOW); delay_us(2); IIC_SCL(HIGH); receive <<= 1; if (READ_SDA) receive++; delay_us(1); } if (!ack) IIC_NAck(); //发送nACK else IIC_Ack(); //发送ACK return receive; } PCF8574.h #ifndef __PCF8574_H #define __PCF8574_H #include "delay.h" #include "Soft_IIC.h" //#define PCF8574_INT PBin(12) //PCF8574 INT脚 #define PCF8574_ADDR 0X40 //PCF8574地址为 0 1 0 0 A2 A1 A0 R/W uint8_t PCF8574_Init(void); uint8_t PCF8574_ReadOneByte(void); void PCF8574_WriteOneByte(uint8_t DataToWrite); void PCF8574_WriteBit(uint8_t bit,uint8_t sta); uint8_t PCF8574_ReadBit(uint8_t bit); #endif PCF8574.c #include "PCF8574.h" //读取PCF8574的8位IO值 //返回值:读到的数据 uint8_t PCF8574_ReadOneByte(void) { uint8_t temp=0; IIC_Start(); IIC_Send_Byte(PCF8574_ADDR|0X01); //进入接收模式 IIC_Wait_Ack(); temp=IIC_Read_Byte(0); IIC_Stop(); //产生一个停止条件 return temp; } //向PCF8574写入8位IO值 //DataToWrite:要写入的数据 void PCF8574_WriteOneByte(uint8_t DataToWrite) { IIC_Start(); IIC_Send_Byte(PCF8574_ADDR|0X00); //发送器件地址0X40,写数据 IIC_Wait_Ack(); IIC_Send_Byte(DataToWrite); //发送字节 IIC_Wait_Ack(); IIC_Stop(); //产生一个停止条件 delay_ms(10); } //设置PCF8574某个IO的高低电平 //bit:要设置的IO编号,0~7 //sta:IO的状态;0或1 void PCF8574_WriteBit(uint8_t bit,uint8_t sta) { uint8_t data; data=PCF8574_ReadOneByte(); //先读出原来的设置 if(sta==0)data&=~(1< } //读取PCF8574的某个IO的值 //bit:要读取的IO编号,0~7 //返回值:此IO的值,0或1 uint8_t PCF8574_ReadBit(uint8_t bit) { uint8_t data; data=PCF8574_ReadOneByte(); //先读取这个8位IO的值 if(data&(1< } 5.main.c中添加代码 (1)包含头文件 #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "delay.h" #include "Soft_IIC.h" #include "PCF8574.h" /* USER CODE END Includes */ (2)声明一个uint8_t 记录PCF8574状态 /* USER CODE BEGIN PV */ uint8_t IIC_READ; /* USER CODE END PV */ (3)主函数 int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ delay_init(8); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { PCF8574_WriteOneByte(0xf0); //置PCF8574高四位高电平 IIC_READ=PCF8574_ReadOneByte(); //读取PCF8574状态 HAL_UART_Transmit(&huart1, &IIC_READ, 1, 0xff); //将PCF8574状态从uart1输出 delay_ms(500); //延时500ms //翻转电平,重复上述操作 PCF8574_WriteOneByte(0x0f); IIC_READ=PCF8574_ReadOneByte(); HAL_UART_Transmit(&huart1, &IIC_READ, 1, 0xff); delay_ms(500); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } 6.设置导出hex文件,buildall 三、实验结果 (1)电平翻转及uart1输出 写入PCF8574信号(0x40 0xf0) |
|
|
|
只有小组成员才能发言,加入小组>>
3314 浏览 9 评论
2995 浏览 16 评论
3494 浏览 1 评论
9059 浏览 16 评论
4088 浏览 18 评论
1178浏览 3评论
605浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
599浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2335浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1896浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 11:12 , Processed in 1.194502 second(s), Total 78, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号