目录
TIM 定时器
TIM.h
#define TIM3_ARR 48-1
#define TIM3_PSC 1000-1
#define TIM3_Priority 0
#define TIM3_SubPriority 1
TIM.c
//TIM3初始化
void DrvTimer3_Init(INT16U arr, INT16U psc) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure={0};
NVIC_InitTypeDef NVIC_InitStructure={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟
TIM_TimeBaseStructure.TIM_Period = arr; //指定下次更新事件时要加载到活动自动重新加载寄存器中的周期值。
TIM_TimeBaseStructure.TIM_Prescaler = psc; //指定用于划分TIM时钟的预分频器值。
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM计数模式,向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
//初始化TIM NVIC,设置中断优先级分组
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //设置响应优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能通道1中断
NVIC_Init(&NVIC_InitStructure); //初始化NVIC
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能TIM3中断,允许更新中断
TIM_Cmd(TIM3, ENABLE); //TIM3使能
}
//TIM3中断
void TIM3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void TIM3_IRQHandler(void) {
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
/*
实现你的功能
*/
}
}
/******************************************************************/
//BSP实现
DrvTimer3_Init(1000-1,48-1);//96M主频
UART/USART 串口收发
Usart.h
#ifndef __DRVUSART_H
#define __DRVUSART_H
#include "stdio.h"
#include "ch32v20x.h"
/* UART Printf Definition */
#define UartPort1 1
#define UartPort2 2
#define UartPort3 3
#define DEBUG_TRUE UartPort2
void DrvUsart_Init(uint8_t DEBUG, uint32_t baudrate);
void DrvUart_SendString(uint8_t Port, INT8U *str, INT8U len);
#if(DEBUG_TRUE)
#define PRINT(format, ...) printf(format, ##__VA_ARGS__)
#else
#define PRINT(X...)
#endif
#endif //__DRVUSART_H
Usart.c
#include "usart.h"
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
//串口初始化(串口1、2、3)
void DrvUsart_Init(uint8_t DEBUG, uint32_t baudrate) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
if (DEBUG == UartPort1) {
RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//PA9-rx PA10-tx
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
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);
} else if (DEBUG == UartPort2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//PA2-tx PA3-rx
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
} else if (DEBUG == UartPort3) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//PB10-tx
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
USART_InitStructure.USART_BaudRate = baudrate;
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;
if (DEBUG == UartPort1) {
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
} else if (DEBUG == UartPort2) {
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART2, ENABLE);
} else if (DEBUG == UartPort3) {
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART3, ENABLE);
}
}
//重定义Print
__attribute__((used))
int _write(int fd, char *buf, int size) {
int i;
for (i = 0; i < size; i++) {
#if(DEBUG_TRUE == UartPort1)
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, *buf++);
#elif(DEBUG_TRUE == UartPort2)
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, *buf++);
#elif(DEBUG_TRUE == UartPort3)
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
USART_SendData(USART3, *buf++);
#endif
}
return size;
}
void *_sbrk(ptrdiff_t incr) {
extern char _end[];
extern char _heap_end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
return NULL - 1;
curbrk += incr;
return curbrk - incr;
}
//串口发送Byte
void DrvUart_SendByte(uint8_t Port, uint8_t byte) {
switch (Port) {
case 1: {
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, byte);
}
break;
case 2: {
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, byte);
}
break;
case 3: {
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
USART_SendData(USART3, byte);
}
break;
default:
break;
}
}
//串口发送String
void DrvUart_SendString(uint8_t Port, INT8U *str, INT8U len) {
INT8U i = 0;
for (i = 0; i < len; i++) {
if (*str == '\r')
DrvUart_SendByte(Port, 0x0d);
else if (*str == '\n')
DrvUart_SendByte(Port, 0x0a);
else
DrvUart_SendByte(Port, *str);
str++;
}
}
//串口1中断 DevProtocol_SetArray为处理接收数据的函数
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
DevProtocol_SetArray(USART_ReceiveData(USART1));
}
}
//串口2中断
void USART2_IRQHandler(void) {
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
DevProtocol_SetArray(USART_ReceiveData(USART2));
}
}
//串口3中断
void USART3_IRQHandler(void) {
if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
DevProtocol_SetArray(USART_ReceiveData(USART3));
}
}
/***************************************************************/
//BSP实现
DrvUsart_Init(UartPort1,115200);
DrvUsart_Init(UartPort2,115200);
DrvUsart_Init(UartPort3,115200);
CAN 总线收发
CAN.h
#ifndef __DRVCAN_H
#define __DRVCAN_H
#include "stdio.h"
#include "ch32v20x.h"
/************************struct******************************/
typedef enum
{
can_bps_125k,
can_bps_250k,
can_bps_500k,
can_bps_1000k,
}CanBps;
/************************function******************************/
void DrvCan_Init(CanBps bps);
void DrvCan_SendMsg(INT8U slaver,INT8U cmd,INT8U motor_num,INT8U* msg,INT8U len);
u8 CAN_Receive_Msg(u8 *buf) ;
#endif //__DRVCAN_H
CAN.c
#include "CAN.h"
void USB_LP_CAN1_RX0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*
*********************************************************************************************************
* 函 数 名 : DrvCan_Init
* 功能说明: CAN1初始化
* 形 参 : 无
* 返 回 值 : 无
* 创 建 人 : MXG
* 创建时间: 20230419
*********************************************************************************************************
*/
void DrvCan_Init(CanBps bps) {
GPIO_InitTypeDef GPIO_InitSturcture;
CAN_InitTypeDef CAN_InitSturcture;
CAN_FilterInitTypeDef CAN_FilterInitSturcture;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
//CAN1-tx
GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_9;
GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitSturcture.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitSturcture);
//CAN1-rx
GPIO_InitSturcture.GPIO_Pin = GPIO_Pin_8;
GPIO_InitSturcture.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitSturcture);
CAN_InitSturcture.CAN_TTCM = DISABLE;
CAN_InitSturcture.CAN_ABOM = DISABLE;
CAN_InitSturcture.CAN_AWUM = DISABLE;
CAN_InitSturcture.CAN_NART = ENABLE;
CAN_InitSturcture.CAN_RFLM = DISABLE;
CAN_InitSturcture.CAN_TXFP = DISABLE;
CAN_InitSturcture.CAN_Mode = CAN_Mode_Normal;
switch (bps) {
case can_bps_125k:
CAN_InitSturcture.CAN_SJW = CAN_SJW_1tq;
CAN_InitSturcture.CAN_BS1 = CAN_BS1_3tq;
CAN_InitSturcture.CAN_BS2 = CAN_BS2_4tq;
CAN_InitSturcture.CAN_Prescaler = 48;
break;
case can_bps_250k:
CAN_InitSturcture.CAN_SJW = CAN_SJW_1tq;
CAN_InitSturcture.CAN_BS1 = CAN_BS1_3tq;
CAN_InitSturcture.CAN_BS2 = CAN_BS2_4tq;
CAN_InitSturcture.CAN_Prescaler = 24;
break;
case can_bps_500k:
CAN_InitSturcture.CAN_SJW = CAN_SJW_1tq;
CAN_InitSturcture.CAN_BS1 = CAN_BS1_3tq;
CAN_InitSturcture.CAN_BS2 = CAN_BS2_4tq;
CAN_InitSturcture.CAN_Prescaler = 12;
break;
case can_bps_1000k:
CAN_InitSturcture.CAN_SJW = CAN_SJW_1tq;
CAN_InitSturcture.CAN_BS1 = CAN_BS1_3tq;
CAN_InitSturcture.CAN_BS2 = CAN_BS2_4tq;
CAN_InitSturcture.CAN_Prescaler = 6;
break;
default:
break;
}
CAN_Init(CAN1, &CAN_InitSturcture);
CAN_FilterInitSturcture.CAN_FilterNumber = 0;
CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitSturcture.CAN_FilterIdHigh = 0;
CAN_FilterInitSturcture.CAN_FilterIdLow = 0;
CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0;
CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0;
CAN_FilterInitSturcture.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
CAN_FilterInitSturcture.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitSturcture);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*
*********************************************************************************************************
* 函 数 名: DrvCan_SendMsg
* 功能说明: Can发送数据
* 形 参: slaver 从设备ID,cmd 命令码,motor_num 电机号,msg数据,len长度
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20220219
*********************************************************************************************************
*/
void DrvCan_SendMsg(INT8U slaver,INT8U cmd,INT8U motor_num,INT8U* msg,INT8U len)
{
u8 TransmitMailbox = 0;
INT16U i = 0;
INT16U Time_out = 0xFFFF;
CanTxMsg CAN_TxMessage;
CAN_TxMessage.ExtId = (motor_num <<16)+(cmd <<8) + slaver; // 设置扩展标示符(29位)
CAN_TxMessage.IDE = CAN_ID_EXT;
CAN_TxMessage.RTR = CAN_RTR_Data;
CAN_TxMessage.DLC = len;
for(i=0;i<len;i++)
{
CAN_TxMessage.Data[i] = msg[i]; //数据帧
}
TransmitMailbox = CAN_Transmit(CAN1, &CAN_TxMessage);
while ((CAN_TransmitStatus(CAN1, TransmitMailbox) != CAN_TxStatus_Ok) && (Time_out != 0)) //等待发送结束
Time_out--;
Time_out = 0xFFFF;
}
/*
*********************************************************************************************************
* 函 数 名: USB_LP_CAN1_RX0_IRQHandler
* 功能说明: Can中断接收
* 形 参: 无
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20220219
*********************************************************************************************************
*/
void USB_LP_CAN1_RX0_IRQHandler(void)
{
CanRxMsg CanRxStructure;
if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET)
{
CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);
CAN_Receive(CAN1, CAN_FIFO1, &CanRxStructure);
DevProtocol_CanProcess(CanRxStructure);
}
}
/***************************************************************/
//BSP实现
DrvCan_Init(can_bps_1000k);
IIC 硬件
IIC.h
#if USE_HARDWARE_IIC //硬件IIC
#define MASTER_MODE 0 //主机
#define SLAVE_MODE 1 //从机
#define I2C_MODE MASTER_MODE
#define SlaveAddress 0X0C //MT6701 地址
#define ReadAddress1 0X03 //数据高位寄存器地址
#define ReadAddress2 0X04 //数据低位寄存器地址
void IIC_Init(u32 bound, u16 address);
void IIC2_Read(u16 ReadAddr, u8 *pBuffer, u16 NumToRead);
IIC.c
/*
*********************************************************************************************************
* 函 数 名 : IIC_Init
* 功能说明: IIC初始化
* 形 参 : 无
* 返 回 值 : 无
* 创 建 人 : MXG
* 创建时间: 20230419
*********************************************************************************************************
*/
void IIC_Init(u32 bound, u16 address) {
GPIO_InitTypeDef GPIO_InitStructure = { 0 };
I2C_InitTypeDef I2C_InitTSturcture = { 0 };
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C2, ENABLE);
//SCL
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure);
//SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOB, &GPIO_InitStructure);
I2C_InitTSturcture.I2C_ClockSpeed = bound;
I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitTSturcture.I2C_OwnAddress1 = address;
I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init( I2C2, &I2C_InitTSturcture);
I2C_Cmd( I2C2, ENABLE);
I2C_AcknowledgeConfig( I2C2, ENABLE);
}
/*
*********************************************************************************************************
* 函 数 名 : IIC2_ReadOneByte
* 功能说明: 读1byte
* 形 参 : ReadAddr-读写地址
* 返 回 值 : 无
* 创 建 人 : MXG
* 创建时间: 20230419
*********************************************************************************************************
*/
u8 IIC2_ReadOneByte(u16 ReadAddr) {
u8 temp = 0;
while( I2C_GetFlagStatus( I2C2, I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( I2C2, ENABLE);
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C2, 0XC, I2C_Direction_Transmitter);
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
#if (Address_Lenth == Address_8bit)
I2C_SendData( I2C2, (u8) (ReadAddr & 0x00FF));
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
#elif (Address_Lenth == Address_16bit)
I2C_SendData( I2C2, (u8)(ReadAddr>>8) );
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_SendData( I2C2, (u8)(ReadAddr&0x00FF) );
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
#endif
I2C_GenerateSTART( I2C2, ENABLE);
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C2, 0X0C, I2C_Direction_Receiver);
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) );
while( I2C_GetFlagStatus( I2C2, I2C_FLAG_RXNE ) == RESET )
I2C_AcknowledgeConfig( I2C2, DISABLE );
temp = I2C_ReceiveData( I2C2);
I2C_GenerateSTOP( I2C2, ENABLE);
return temp;
}
/*
*********************************************************************************************************
* 函 数 名 : IIC2_WriteOneByte
* 功能说明: WriteAddr-写地址 DataToWrite-写数据
* 形 参 : 无
* 返 回 值 : 无
* 创 建 人 : MXG
* 创建时间: 20230419
*********************************************************************************************************
*/
void IIC2_WriteOneByte(u16 WriteAddr, u8 DataToWrite) {
while( I2C_GetFlagStatus( I2C2, I2C_FLAG_BUSY ) != RESET );
I2C_GenerateSTART( I2C2, ENABLE);
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_MODE_SELECT ) );
I2C_Send7bitAddress( I2C2, 0X0C, I2C_Direction_Transmitter);
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
#if (Address_Lenth == Address_8bit)
I2C_SendData( I2C2, (u8) (WriteAddr & 0x00FF));
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
#elif (Address_Lenth == Address_16bit)
I2C_SendData( I2C2, (u8)(WriteAddr>>8) );
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_SendData( I2C2, (u8)(WriteAddr&0x00FF) );
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
#endif
if (I2C_GetFlagStatus( I2C2, I2C_FLAG_TXE) != RESET) {
I2C_SendData( I2C2, DataToWrite);
}
while( !I2C_CheckEvent( I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
I2C_GenerateSTOP( I2C2, ENABLE);
}
/*
*********************************************************************************************************
* 函 数 名 : IIC2_Read
* 功能说明: 连续读
* 形 参 : ReadAddr-读地址 pBuffer-存放数组 NumToRead-长度
* 返 回 值 : 无
* 创 建 人 : MXG
* 创建时间: 20230419
*********************************************************************************************************
*/
void IIC2_Read(u16 ReadAddr, u8 *pBuffer, u16 NumToRead) {
while(NumToRead)
{
*pBuffer++=IIC2_ReadOneByte(ReadAddr++);
NumToRead--;
}
}
/*
*********************************************************************************************************
* 函 数 名 : IIC2_Write
* 功能说明: 连续写
* 形 参 : WriteAddr-写地址 pBuffer-写数据 NumToWrite-长度
* 返 回 值 : 无
* 创 建 人 : MXG
* 创建时间: 20230419
*********************************************************************************************************
*/
void IIC2_Write(u16 WriteAddr, u8 *pBuffer, u16 NumToWrite) {
while(NumToWrite--)
{
IIC2_WriteOneByte(WriteAddr,*pBuffer);
WriteAddr++;
pBuffer++;
Delay_Ms(2);
}
}
IIC 软件
IIC.h
#define I2C_ADDRESS 0X0C
#define I2C_SCL_PORT GPIOB
#define I2C_SCL_PIN GPIO_Pin_10
#define I2C_SDA_PORT GPIOB
#define I2C_SDA_PIN GPIO_Pin_11
#define I2C_SDA_H GPIO_SetBits(I2C_SDA_PORT, I2C_SDA_PIN)
#define I2C_SDA_L GPIO_ResetBits(I2C_SDA_PORT, I2C_SDA_PIN)
#define I2C_SDA_R GPIO_ReadInputDataBit(I2C_SDA_PORT, I2C_SDA_PIN)
#define I2C_SCL_H GPIO_SetBits(I2C_SCL_PORT, I2C_SCL_PIN)
#define I2C_SCL_L GPIO_ResetBits(I2C_SCL_PORT, I2C_SCL_PIN)
#define IIC_OK 1
#define IIC_Err 0
#define ACK_TIME (200U)
/*********** Struct **********/
typedef struct
{
INT16U speed;
} IIC_INFO;
typedef enum
{
err_none =1,
err_timout_t,
err_timout_r,
err_max_addr,
}err_I2C_code;
IIC.C
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_Init
* 功能说明: i2c初始化
* 形 参: 无
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
void DrvI2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//PB10-SCL
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出,不用切换输入和输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_SCL_PORT, &GPIO_InitStructure);
//PB11-SDA
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出,不用切换输入和输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(I2C_SDA_PORT, &GPIO_InitStructure);
I2C_SDA_H;
I2C_SCL_H;
}
//IIC空闲状态
//当IIC总线的SDA和SCL两条信号线同时处于高电平时,规定为IIC总线的空闲状态
void I2C_Idle_State()
{
I2C_SDA_H;
I2C_SCL_H;
Delay_Us(4);
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_Start
* 功能说明: 软件IIC开始信号
* 形 参: 无
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
void DrvI2C_Start(void)
{
I2C_SDA_H;
I2C_SCL_H;
Delay_Us(4);
I2C_SDA_L;
Delay_Us(4);
I2C_SCL_L;
Delay_Us(4);
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_Stop
* 功能说明: 软件IIC停止信号
* 形 参: 无
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
void DrvI2C_Stop(void)
{
I2C_SDA_L; //拉低SDA线
I2C_SCL_L; //拉低SCL先
Delay_Us(4);
I2C_SCL_H; //拉高SCL线
I2C_SDA_H; //拉高SDA线,当SCL线为高时,SDA线一个上升沿代表停止信号
Delay_Us(4);
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_WaitAck
* 功能说明: 软件IIC等待ACK应答
* 形 参: 超时时间
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
u8 DrvI2C_WaitAck(INT32U timeOut)
{
I2C_SDA_H; //拉高SDA线
Delay_Us(4);
I2C_SCL_H; //拉高SCL线
Delay_Us(4);
while(I2C_SDA_R) //如果读到SDA线为1,则等待。应答信号应是0
{
if(--timeOut == 0)
{
DrvI2C_Stop(); //超时未收到应答,则停止总线
return IIC_Err; //返回失败
}
Delay_Us(4);
}
I2C_SCL_L; //拉低SCL线,以便继续收发数据
return IIC_OK; //返回成功
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_Ack
* 功能说明: 软件IIC产生一个应答
* 形 参: 无
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
void DrvI2C_Ack(void)
{
I2C_SCL_L; //拉低SCL线
I2C_SDA_L; //拉低SDA线
Delay_Us(4);
I2C_SCL_H; //拉高SCL线
Delay_Us(4);
I2C_SCL_L; //拉低SCL线
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_Ack
* 功能说明: 软件IIC产生一个非应答
* 形 参: 无
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
void DrvI2C_NAck(void)
{
I2C_SCL_L; //拉低SCL线
I2C_SDA_H; //拉高SDA线
Delay_Us(4);
I2C_SCL_H; //拉高SCL线
Delay_Us(4);
I2C_SCL_L; //拉低SCL线
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_SendByte
* 功能说明: 软件IIC发送一个字节
* 形 参: 需要发送的字节
* 返 回 值: 无
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
void DrvI2C_SendByte(INT8U byte)
{
INT8U count = 0;
I2C_SCL_L; //拉低时钟开始数据传输
for(; count < 8; count++) //循环8次,每次发送一个bit
{
if(byte & 0x80) //发送最高位
I2C_SDA_H;
else
I2C_SDA_L;
byte <<= 1; //byte左移1位
Delay_Us(4);
I2C_SCL_H;
Delay_Us(4);
I2C_SCL_L;
}
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_RecvByte
* 功能说明: 软件IIC接收一个字节
* 形 参: 无
* 返 回 值: 接收到的字节
* 创 建 人: MXG
* 创建时间: 20201109
*********************************************************************************************************
*/
INT8U DrvI2C_RecvByte(void)
{
INT8U count = 0, receive = 0;
I2C_SDA_H; //拉高SDA线,开漏状态下,需线拉高以便读取数据
for(; count < 8; count++ ) //循环8次,每次发送一个bit
{
I2C_SCL_L;
Delay_Us(4);
I2C_SCL_H;
receive <<= 1; //左移一位
if(I2C_SDA_R) //如果SDA线为1,则receive变量自增,每次自增都是对bit0的+1,然后下一次循环会先左移一次
receive++;
Delay_Us(4);
}
return receive;
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_ReadByte
* 功能说明: 读数据
* 形 参: 起始地址
* 返 回 值: 成功/失败
* 创 建 人: MXG
* 创建时间: 20210125
*********************************************************************************************************
*/
INT8U DrvI2C_ReadByte(INT8U ReadAddr,INT8U *data)
{
DrvI2C_Start();
DrvI2C_SendByte(I2C_ADDRESS); //发送写命令
*data = 0;
if( !DrvI2C_WaitAck(ACK_TIME))
return err_timout_t;
DrvI2C_SendByte(ReadAddr&0xff); //发送地址
if( !DrvI2C_WaitAck(ACK_TIME))
return err_timout_t;
DrvI2C_Start();
DrvI2C_SendByte(I2C_ADDRESS+1); //发送读命令
if( !DrvI2C_WaitAck(ACK_TIME))
return err_timout_t;
*data=DrvI2C_RecvByte();
DrvI2C_NAck(); //不带ACK的
DrvI2C_Stop();//产生一个停止条件
return 1; //status == 0;
}
/*
*********************************************************************************************************
* 函 数 名: DrvI2C_ReadBytes
* 功能说明: 读多个数据
* 形 参: 起始地址
* 返 回 值: 成功/失败
* 创 建 人: MXG
* 创建时间: 20210125
*********************************************************************************************************
*/
INT8U DrvI2C_ReadBytes(INT8U ReadAddr,INT16U length,INT8U *data)
{
INT16U count = 0;
for( count = 0; count < length; count ++)
{
DrvI2C_ReadByte(ReadAddr +count,&data[count]);
}
return 0;
}
#endif
Flash擦写(字)
.h
/* Global define */
typedef enum {
FAILED = 0, PASSED = !FAILED
} TestStatus;
#define PAGE_WRITE_START_ADDR ((uint32_t)0x0800F000) /* Start from 60K */
#define PAGE_WRITE_END_ADDR ((uint32_t)0x08010000) /* End at 64K */
#define FLASH_PAGE_SIZE 4096
#define FLASH_PAGES_TO_BE_PROTECTED FLASH_WRProt_Pages60to63
/* Fast Mode define */
#define FAST_FLASH_PROGRAM_START_ADDR ((uint32_t)0x08008000) //32K
#define FAST_FLASH_PROGRAM_END_ADDR ((uint32_t)0x08010000) //64k
#define FAST_FLASH_SIZE (64*1024) //Flash总内存
.c
/************************************************************
* File Name: DrvFlash.c
* File Instruction: 该文件为Flash驱动文件
* File User: Phyllis
* File TIME: 2022-02-19
* File Version: V1.0
************************************************************/
#include "flash.h"
/* Global Variable */
uint32_t EraseCounter = 0x0, Address = 0x0;
uint16_t Data = 0xAAAA;
uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0x0;
uint32_t NbrOfPage;
volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;
volatile TestStatus MemoryProgramStatus = PASSED;
volatile TestStatus MemoryEraseStatus = PASSED;
u32 buf[64];
/*
*********************************************************************************************************
* 函 数 名: DrvFlash_WriteWords
* 功能说明: Flash写一个word,32位
* 形 参: 地址,数据,字长
* 返 回 值: 错误码
* 创 建 人: MXG
* 创建时间: 20220219
*********************************************************************************************************
*/
errcode DrvFlash_WriteWords(INT32U addr, INT32U *buff, INT32U len) {
errcode err_code = flasherr_none;
INT8U i = 0;
//系统时钟超过100M时需要降频
RCC->CFGR0 |= (uint32_t) RCC_HPRE_DIV2;
__disable_irq();
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
//擦
FLASHStatus = FLASH_ErasePage(addr); //Erase 4KB
if (FLASHStatus != FLASH_COMPLETE) {
err_code = flasherr_Erase;
return err_code;
}
Address = addr;
//写
while((i < len) && (FLASHStatus == FLASH_COMPLETE))
{
FLASHStatus = FLASH_ProgramWord(Address, buff[i++]);
Address = Address + 4;
}
FLASH_Lock();
RCC->CFGR0 &= ~(uint32_t) RCC_HPRE_DIV2;
__enable_irq();
return err_code;
}
/*
*********************************************************************************************************
* 函 数 名: DrvFlash_ReadWord
* 功能说明: Flash读一个word
* 形 参: 地址
* 返 回 值: 数据
* 创 建 人: MXG
* 创建时间: 20220219
*********************************************************************************************************
*/
INT32U DrvFlash_ReadWord(INT32U addr) {
return *(vu32*) addr;
}
/*
*********************************************************************************************************
* 函 数 名: DrvFlash_ReadWords
* 功能说明: Flash读多个world
* 形 参: 地址
* 返 回 值: 数据
* 创 建 人: MXG
* 创建时间: 20220219
*********************************************************************************************************
*/
errcode DrvFlash_ReadWords(INT32U addr, INT32U *buff, INT32U len) {
INT8U i = 0;
errcode err_code = flasherr_none;
//对4k
// for(i=0; i<1024; i++){
// buff[i] = *(u32*)(PAGE_WRITE_START_ADDR+4*i);
// }
for(i=0; i<len; i++){
buff[i] = *(u32*)(addr+4*i);
}
return err_code;
}
更新ing...