第一版代码,为了在EEPROM保存参数的时候走STM32的CRC,让Codex修改了一下,现在的效果是无法存储,codex表示原因是CRC方法不同,修改到一半今天的额度使用完了,有待后续解决CRC的bug
This commit is contained in:
61
MyDriver/DWT.c
Normal file
61
MyDriver/DWT.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "DWT.h"
|
||||
|
||||
// 寄存器基地址
|
||||
#define DWT_CR (*(uint32_t *)0xE0001000)
|
||||
#define DWT_CYCCNT (*(uint32_t *)0xE0001004)
|
||||
#define DEM_CR (*(uint32_t *)0xE000EDFC)
|
||||
|
||||
// 定义需使能位
|
||||
#define DEM_CR_TRCENA (1 << 24)
|
||||
#define DWT_CR_CYCCNTENA (1 << 0)
|
||||
|
||||
// DWT init
|
||||
void DWT_init(void)
|
||||
{
|
||||
DEM_CR |= (uint32_t)DEM_CR_TRCENA;
|
||||
DWT_CYCCNT = (uint32_t)0u;
|
||||
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
|
||||
}
|
||||
// get DWT count
|
||||
uint32_t DWT_TS_GET(void)
|
||||
{
|
||||
return ((uint32_t)DWT_CYCCNT);
|
||||
}
|
||||
|
||||
// 使用DWT延时time_us微秒
|
||||
void DWT_delay_us(uint32_t time_us)
|
||||
{
|
||||
uint32_t old_counter, current_counter;
|
||||
uint32_t delay_us;
|
||||
|
||||
old_counter = DWT_TS_GET();
|
||||
current_counter = DWT_TS_GET();
|
||||
delay_us = 0;
|
||||
while (delay_us < time_us)
|
||||
{
|
||||
current_counter = DWT_TS_GET();
|
||||
if (current_counter > old_counter)
|
||||
delay_us = (current_counter - old_counter) / (SystemCoreClock / 1000000);
|
||||
else
|
||||
delay_us = (current_counter + 0XFFFFFFFF - old_counter) / (SystemCoreClock / 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
// 使用DWT延时time_ms毫秒
|
||||
void DWT_delay_ms(uint32_t time_ms)
|
||||
{
|
||||
uint32_t old_counter, current_counter;
|
||||
uint32_t delay_ms;
|
||||
|
||||
old_counter = DWT_TS_GET();
|
||||
current_counter = DWT_TS_GET();
|
||||
delay_ms = 0;
|
||||
while (delay_ms < time_ms)
|
||||
{
|
||||
current_counter = DWT_TS_GET();
|
||||
if (current_counter > old_counter)
|
||||
delay_ms = (current_counter - old_counter) / (SystemCoreClock / 1000);
|
||||
else
|
||||
delay_ms = (current_counter + 0XFFFFFFFF - old_counter) / (SystemCoreClock / 1000);
|
||||
}
|
||||
}
|
||||
15
MyDriver/DWT.h
Normal file
15
MyDriver/DWT.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __DMT_H__
|
||||
#define __DMT_H__
|
||||
|
||||
#include "stm32f407xx.h"
|
||||
|
||||
// DWT init
|
||||
void DWT_init(void);
|
||||
|
||||
// 使用DWT延时time_ms毫秒
|
||||
void DWT_delay_ms(uint32_t time_ms);
|
||||
|
||||
// 使用DWT延时time_us微秒
|
||||
void DWT_delay_us(uint32_t time_us);
|
||||
|
||||
#endif /* __DMT_H__ */
|
||||
208
MyDriver/SoftI2C.c
Normal file
208
MyDriver/SoftI2C.c
Normal file
@@ -0,0 +1,208 @@
|
||||
#include "SoftI2C.h"
|
||||
|
||||
void Dri_I2C_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
// 1. 时钟使能GPIOA
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
// 2. 设置引脚模式,PA8(SDA), PA9(SCL)设置为通用开漏输出
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 通用开漏输出
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
// 发送起始信号
|
||||
void Dri_I2C_Start(void)
|
||||
{
|
||||
// 拉高SCL、拉高SDA、延时
|
||||
SCL_HIGH;
|
||||
SDA_HIGH;
|
||||
SCL_DELAY;
|
||||
|
||||
// 拉低SDA,下降沿表示起始信号; 延时
|
||||
SDA_LOW;
|
||||
SCL_DELAY;
|
||||
|
||||
// 拉低SCL,方便发送方修改SDA
|
||||
SCL_LOW;
|
||||
SCL_DELAY;
|
||||
}
|
||||
|
||||
// 发送停止信号
|
||||
void Dri_I2C_Stop(void)
|
||||
{
|
||||
// 在拉高SCL之前,先拉低SDA (避免意外产生起始信号)
|
||||
SDA_LOW;
|
||||
|
||||
// 拉高SCL并延时
|
||||
SCL_HIGH;
|
||||
SCL_DELAY;
|
||||
|
||||
// SCL高电平期间拉高SDA,发起结束信号
|
||||
SDA_HIGH;
|
||||
SCL_DELAY;
|
||||
}
|
||||
|
||||
// 发送一个字节的数据
|
||||
void Dri_I2C_TransmitByte(uint8_t byte)
|
||||
{
|
||||
// 分8次逐bit发送,先发高位
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
// 判断当前 byte 的最高位
|
||||
if (byte & 0x80)
|
||||
{
|
||||
SDA_HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
SDA_LOW;
|
||||
}
|
||||
|
||||
// 拉高时钟并延时,让接收方采样
|
||||
SCL_HIGH;
|
||||
SCL_DELAY;
|
||||
|
||||
// byte 左移1位
|
||||
byte <<= 1;
|
||||
|
||||
// 拉低SCL,好准备下一个要发的数据
|
||||
SCL_LOW;
|
||||
SCL_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
// 接收一个字节的数据
|
||||
uint8_t Dri_I2C_ReceiveByte(void)
|
||||
{
|
||||
// 释放数据总线
|
||||
SDA_HIGH;
|
||||
|
||||
// 定义变量,用于接收数据
|
||||
uint8_t byte = 0;
|
||||
|
||||
// 分8次逐bit接收,先收高位
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
// 拉高SCL
|
||||
SCL_HIGH;
|
||||
|
||||
// byte 左移1位,空出最低位用于接收当前的bit
|
||||
byte <<= 1;
|
||||
|
||||
// 读SDA, 如果SDA是高电平
|
||||
if (SDA_READ)
|
||||
{
|
||||
byte |= 0x01;
|
||||
}
|
||||
|
||||
// 延时
|
||||
SCL_DELAY;
|
||||
|
||||
// 拉低SCL并延时,让发送方准备数据
|
||||
SCL_LOW;
|
||||
SCL_DELAY;
|
||||
}
|
||||
|
||||
// 返回
|
||||
return byte;
|
||||
}
|
||||
|
||||
// 发送一个ACK信号, 参数是0(ACK)或1(NACK)
|
||||
void Dri_I2C_TransmitACK(uint8_t ack)
|
||||
{
|
||||
if (ack)
|
||||
{
|
||||
// 发送NACK
|
||||
SDA_HIGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 发送ACK
|
||||
SDA_LOW;
|
||||
}
|
||||
|
||||
// 拉高时钟并延时
|
||||
SCL_HIGH;
|
||||
SCL_DELAY;
|
||||
|
||||
// 高低时钟并延时
|
||||
SCL_LOW;
|
||||
SCL_DELAY;
|
||||
}
|
||||
|
||||
// 接收一个ACK信号并返回
|
||||
uint8_t Dri_I2C_ReceiveACK(void)
|
||||
{
|
||||
// 定义变量保存收到的ack信号
|
||||
uint8_t ack = 0;
|
||||
|
||||
// 释放数据总线
|
||||
SDA_HIGH;
|
||||
|
||||
// 拉高SCL
|
||||
SCL_HIGH;
|
||||
|
||||
// 读取SDA
|
||||
ack = SDA_READ ? 1 : 0;
|
||||
// 延时
|
||||
SCL_DELAY;
|
||||
|
||||
// 拉低SCL并延时
|
||||
SCL_LOW;
|
||||
SCL_DELAY;
|
||||
|
||||
return ack;
|
||||
}
|
||||
|
||||
void Dri_I2C_WriteAddr(uint8_t slave_addr)
|
||||
{
|
||||
Dri_I2C_TransmitByte(slave_addr);
|
||||
uint8_t ack = Dri_I2C_ReceiveACK();
|
||||
if (ack)
|
||||
{
|
||||
debug_printf("I2C send slave address error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Dri_I2C_WriteReg(uint8_t reg, uint8_t data)
|
||||
{
|
||||
Dri_I2C_TransmitByte(reg);
|
||||
uint8_t ack = Dri_I2C_ReceiveACK();
|
||||
if (ack)
|
||||
{
|
||||
debug_printf("I2C send register address error");
|
||||
return;
|
||||
}
|
||||
Dri_I2C_TransmitByte(data);
|
||||
ack = Dri_I2C_ReceiveACK();
|
||||
if (ack)
|
||||
{
|
||||
debug_printf("I2C send register data error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Dri_I2C_ReadReg(uint8_t slave_addr_read, uint8_t reg)
|
||||
{
|
||||
Dri_I2C_Start();
|
||||
Dri_I2C_WriteAddr(slave_addr_read - 1);
|
||||
Dri_I2C_TransmitByte(reg);
|
||||
uint8_t ack = Dri_I2C_ReceiveACK();
|
||||
if (ack)
|
||||
{
|
||||
debug_printf("I2C send register address error");
|
||||
return 0;
|
||||
}
|
||||
Dri_I2C_Start();
|
||||
Dri_I2C_WriteAddr(slave_addr_read);
|
||||
uint8_t data = Dri_I2C_ReceiveByte();
|
||||
Dri_I2C_TransmitACK(0);
|
||||
Dri_I2C_Stop();
|
||||
return data;
|
||||
}
|
||||
43
MyDriver/SoftI2C.h
Normal file
43
MyDriver/SoftI2C.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef __DRIVER_I2C_H__
|
||||
#define __DRIVER_I2C_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "stm32f407xx.h"
|
||||
#include "stm32f4xx.h"
|
||||
#include "main.h"
|
||||
#include "Com_debug.h"
|
||||
#include "DWT.h"
|
||||
|
||||
// PA8是SDA,PA9是SCL
|
||||
// 板子改进意见:PE9和PE11用作定时器1的CH1和CH2,然后PA8和PA9留出来用作I2C的通信引脚
|
||||
#define I2C_SCL_PIN GPIO_PIN_9
|
||||
#define I2C_SDA_PIN GPIO_PIN_8
|
||||
#define I2C_GPIO_PORT GPIOA
|
||||
|
||||
// 宏定义 SDA拉高或拉低
|
||||
#define SDA_HIGH I2C_GPIO_PORT->BSRR = I2C_SDA_PIN
|
||||
#define SDA_LOW I2C_GPIO_PORT->BSRR = (uint32_t)I2C_SDA_PIN << 16U
|
||||
|
||||
// 宏定义 SCL拉高或拉低
|
||||
#define SCL_HIGH I2C_GPIO_PORT->BSRR = I2C_SCL_PIN
|
||||
#define SCL_LOW I2C_GPIO_PORT->BSRR = (uint32_t)I2C_SCL_PIN << 16U
|
||||
|
||||
// 宏定义 读SDA
|
||||
#define SDA_READ (I2C_GPIO_PORT->IDR & I2C_SDA_PIN)
|
||||
|
||||
// 宏定义 延时5us
|
||||
#define SCL_DELAY DWT_delay_us(5)
|
||||
|
||||
void Dri_I2C_Init(void); // 初始化函数
|
||||
void Dri_I2C_Start(void); // 发送起始信号
|
||||
void Dri_I2C_Stop(void); // 发送停止信号
|
||||
void Dri_I2C_TransmitByte(uint8_t byte); // 发送一个字节的数据
|
||||
uint8_t Dri_I2C_ReceiveByte(void); // 接收一个字节的数据
|
||||
void Dri_I2C_TransmitACK(uint8_t ack); // 发送一个ACK信号, 参数是0(ACK)或1(NACK)
|
||||
uint8_t Dri_I2C_ReceiveACK(void); // 接收一个ACK信号并返回
|
||||
|
||||
void Dri_I2C_WriteAddr(uint8_t slave_addr); // 写从机地址
|
||||
void Dri_I2C_WriteReg(uint8_t reg, uint8_t data); // 写一个寄存器
|
||||
uint8_t Dri_I2C_ReadReg(uint8_t slave_addr_read, uint8_t reg); // 读一个寄存器
|
||||
|
||||
#endif /* __DRIVER_I2C_H__ */
|
||||
Reference in New Issue
Block a user