#define IIC_US (MHZ*1000000/5000000/2)四舍五入取正方式代码
时间: 2024-11-03 14:17:40 浏览: 11
#define IIC_US (MHZ*1000000/5000000/2) 是一个宏定义,用于计算IIC通信的时钟周期。
首先,这个宏定义使用了四舍五入取正的方式。在C语言中,整数除法会自动向下取整,所以为了实现四舍五入的效果,我们需要对结果进行一些处理。
具体来说,我们可以将分子加上分母的一半,然后再进行整数除法。这样可以确保当存在小数部分时,结果会向上取整。
例如,如果 MHZ 是 10,那么:
```
(MHZ*1000000 + 5000000/2) / 5000000 = (10*1000000 + 250000) / 5000000 = (10000000 + 250000) / 5000000 = 10250000 / 5000000 = 2.05
```
由于我们只取整数部分,所以最终结果是 2。
如果我们希望代码更清晰,可以定义一个辅助宏来实现四舍五入取正的功能:
```c
#define ROUND_UP(x, y) (((x) + (y) - 1) / (y))
#define IIC_US (ROUND_UP(MHZ*1000000, 5000000) / 2)
```
这样,无论 MHZ 的值是多少,IIC_US 都会根据上述规则计算出正确的值。
相关问题
你是一名程序员,现在要用stm32f103ze给超声波模块GY_US42改IIC地址,并能够在串口调试助手查看模块的IIC地址,要求使用标准库写一份完整的代码,,完整代码包含IIC发送和接收函数,更改地址函数,mian函数,串口相关函数
好的,以下是我写的完整代码:
```c
#include "stm32f10x.h"
#include "stdio.h"
#define GY_US42_ADDR 0xE0 // GY-US42默认IIC地址
#define NEW_ADDR 0xE2 // 要改为的新IIC地址
void I2C_GPIO_Config(void);
void I2C_Config(void);
void I2C_SendByte(uint8_t addr, uint8_t data);
uint8_t I2C_ReadByte(uint8_t addr);
void GY_US42_SetAddr(uint8_t newAddr);
void USART1_Config(void);
void USART1_SendChar(char c);
void USART1_SendString(char* str);
void delay_ms(uint32_t ms);
int main(void)
{
SystemInit();
I2C_GPIO_Config();
I2C_Config();
USART1_Config();
GY_US42_SetAddr(NEW_ADDR); // 改变GY-US42的IIC地址为NEW_ADDR
while (1)
{
uint8_t addr = I2C_ReadByte(GY_US42_ADDR); // 读取GY-US42的IIC地址
char buf[20];
sprintf(buf, "IIC Addr: 0x%x\r\n", addr);
USART1_SendString(buf);
delay_ms(1000);
}
}
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_Config(void)
{
I2C_InitTypeDef I2C_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
void I2C_SendByte(uint8_t addr, uint8_t data)
{
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, data);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
}
uint8_t I2C_ReadByte(uint8_t addr)
{
uint8_t data;
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Receiver);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
data = I2C_ReceiveData(I2C1);
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
return data;
}
void GY_US42_SetAddr(uint8_t newAddr)
{
I2C_SendByte(GY_US42_ADDR, 0xA0);
I2C_SendByte(GY_US42_ADDR, 0xAA);
I2C_SendByte(GY_US42_ADDR, 0xA5);
I2C_SendByte(GY_US42_ADDR, newAddr);
}
void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void USART1_SendChar(char c)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, c);
}
void USART1_SendString(char* str)
{
while (*str)
{
USART1_SendChar(*str++);
}
}
void delay_ms(uint32_t ms)
{
SysTick->LOAD = 72000 - 1;
SysTick->CTRL = 0x05;
for (uint32_t i = 0; i < ms; i++)
{
while (!(SysTick->CTRL & 0x10000));
}
SysTick->CTRL = 0x00;
}
```
其中,`I2C_GPIO_Config`和`I2C_Config`函数负责配置IIC总线,`I2C_SendByte`和`I2C_ReadByte`函数分别用于发送和接收IIC数据,`GY_US42_SetAddr`函数用于更改GY-US42的IIC地址,`USART1_Config`函数用于配置串口,`USART1_SendChar`和`USART1_SendString`函数分别用于发送单个字符和字符串,`delay_ms`函数用于延时。
在`main`函数中,首先进行各种配置,然后调用`GY_US42_SetAddr`函数将GY-US42的IIC地址更改为`NEW_ADDR`,然后进入一个死循环,每隔一秒读取一次GY-US42的IIC地址并通过串口输出。
stm32f407 模拟 iic代码
STM32F407模拟IIC代码可以使用软件模拟的方式实现。以下是一个简单的示例代码:
```
#include "stm32f4xx.h"
#define IIC_SCL_PIN GPIO_Pin_6
#define IIC_SDA_PIN GPIO_Pin_7
#define IIC_SCL_PORT GPIOB
#define IIC_SDA_PORT GPIOB
// 初始化IIC总线
void IIC_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN | IIC_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);
}
// IIC起始信号
void IIC_Start(void) {
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_PIN);
delay_us(4);
GPIO_ResetBits(IIC_SDA_PORT, IIC_SDA_PIN);
delay_us(4);
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(4);
}
// IIC停止信号
void IIC_Stop(void) {
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
GPIO_ResetBits(IIC_SDA_PORT, IIC_SDA_PIN);
delay_us(4);
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_PIN);
delay_us(4);
}
// IIC等待应答信号
// 返回: 1,接收应答失败
// 0,接收应答成功
uint8_t IIC_Wait_Ack(void) {
uint8_t ucErrTime = 0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(1);
while (GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN)) {
ucErrTime++;
if (ucErrTime > 250) {
IIC_Stop();
return 1;
}
}
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
return 0;
}
// IIC发送一个字节
void IIC_Send_Byte(uint8_t txd) {
uint8_t t;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
for (t = 0; t < 8; t++) {
GPIO_WriteBit(IIC_SDA_PORT, IIC_SDA_PIN, (txd & 0x80) >> 7);
txd <<= 1;
delay_us(2);
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(2);
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(2);
}
}
// IIC读取一个字节
// ack=1,发送ACK
// ack=0,发送NACK
uint8_t IIC_Read_Byte(uint8_t ack) {
uint8_t i, receive = 0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
for (i = 0; i < 8; i++) {
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(2);
receive <<= 1;
receive |= GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN);
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(1);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
// IIC发送应答信号
void IIC_Ack(void) {
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
GPIO_ResetBits(IIC_SDA_PORT, IIC_SDA_PIN);
delay_us(2);
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(2);
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
}
// IIC发送非应答信号
void IIC_NAck(void) {
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
GPIO_SetBits(IIC_SDA_PORT, IIC_SDA_PIN);
delay_us(2);
GPIO_SetBits(IIC_SCL_PORT, IIC_SCL_PIN);
delay_us(2);
GPIO_ResetBits(IIC_SCL_PORT, IIC_SCL_PIN);
}
```
以上是一个简单的STM32F407模拟IIC代码,可以使用该代码来实现IIC通信。需要注意的是,由于是软件模拟,因此需要延时函数来模拟IIC的时序。这里的延时函数需要根据具体的系统时钟频率进行相应的调整。此外,还需根据实际的硬件连接,在代码中正确配置IIC的引脚和端口。
阅读全文