同步步兵代码,暂时关闭底盘跟随

This commit is contained in:
2025-11-02 21:21:11 +08:00
parent 456cc96c81
commit 3821589bed
693 changed files with 238044 additions and 2735 deletions

View File

@@ -0,0 +1,280 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "CAN.h"
#include "M3508.h"
#include "GM6020.h"
#include "M2006.h"
#include "LinkCheck.h"
#include "Warming.h"
#include "CToC.h"
#include "RefereeSystem.h"
uint8_t CAN_CAN1DeviceNumber=4;//CAN1总线上设备数量
uint8_t CAN_CAN2DeviceNumber=2;//CAN2总线上设备数量
uint8_t CAN_DeviceNumber=6;//CAN总线上设备数量
uint32_t CAN_CAN1IDList[10][2]={{CAN_GM6020,GM6020_2},{CAN_M2006,M2006_7},{CAN_M3508,M3508_1},{CAN_M3508,M3508_2},0};//CAN1总线上设备ID列表
uint32_t CAN_CAN2IDList[10][2]={{CAN_GM6020,GM6020_1},{CAN_RoboMasterC,CToC_MasterID1},0};//CAN2总线上设备ID列表
int8_t CAN_IDSelect=0;//CAN总线上ID列表选择位
/*
*函数简介:CAN总线初始化
*参数说明:无
*返回类型:无
*备注:默认使用CAN1(CAN1-Tx为PD1,CAN1-Rx为PD0),CAN2(CAN2-Tx为PB6,CAN2-Rx为PB5)
*备注:CAN波特率1M,默认1Tq=1/14us≈0.07us
*备注:使用CAN2需要在打开CAN2时钟之前打开CAN1时钟,且CAN2筛选器编号为15~27
*/
void CAN_CANInit(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOD,&GPIO_InitStructure);//配置PD0(CAN1-Rx)和PD1(CAN1-Tx)
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOB,&GPIO_InitStructure);//配置PB5(CAN2-Rx)和PB6(CAN2-Tx)
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_CAN1);//开启PD0的CAN1复用模式
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_CAN1);//开启PD1的CAN1复用模式
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_CAN2);//开启PB5的CAN2复用模式
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_CAN2);//开启PB6的CAN2复用模式
CAN_InitTypeDef CAN_InitStructure;
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal;//正常模式
CAN_InitStructure.CAN_Prescaler=3;//时钟分频,1Tq=Prescaler/T_PCLK=Prescaler/42M
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;//SJW极限值
CAN_InitStructure.CAN_BS1=CAN_BS1_10tq;//PBS1段长度
CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;//PBS2段长度,1/Baudrate=T_1bit=(1+BS1+BS2)Tq
CAN_InitStructure.CAN_TTCM=DISABLE;//关闭时间触发功能
CAN_InitStructure.CAN_ABOM=ENABLE;//开启自动离线管理功能
CAN_InitStructure.CAN_AWUM=ENABLE;//开启自动唤醒功能
CAN_InitStructure.CAN_NART=ENABLE;//禁止自动重传功能
CAN_InitStructure.CAN_RFLM=DISABLE;//关闭锁定FIFO功能
CAN_InitStructure.CAN_TXFP=DISABLE;//配置报文优先级判定为标识符决定
CAN_Init(CAN1,&CAN_InitStructure);
CAN_Init(CAN2,&CAN_InitStructure);
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber=0;//筛选器编号0(编号0~14属于CAN1,编号15~27属于CAN2)
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//存入FIFO0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;//掩码模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;//筛选器尺度为16bits
CAN_FilterInitStructure.CAN_FilterIdHigh=(CAN_CAN1IDList[0][1]<<5);//标识符=STID[15:5]+RTR[4:4](0)+IDE[3:3](0)+EXID[2:0](000)
CAN_FilterInitStructure.CAN_FilterIdLow=(CAN_CAN1IDList[0][1]<<5);//筛选器尺度为16bits,故没有高低位之分
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFE3;//掩码(1111 1111 0000 0011),1对应位必须匹配,0对应位无需匹配
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xFFE3;//筛选器尺度为16bits,故没有高低位之分
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;//使能筛选器
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=15;//筛选器编号15(编号0~14属于CAN1,编号15~27属于CAN2)
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1;//存入FIFO1
CAN_FilterInitStructure.CAN_FilterIdHigh=(0x000<<5);//标识符=STID[15:5](189/0001 1000 1001)+RTR[4:4](0)+IDE[3:3](0)+EXID[2:0](000)
CAN_FilterInitStructure.CAN_FilterIdLow=(0x000<<5);//CAN2先给0,默认从CAN1开始串行接收
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//打通CAN1_FIFO0到NVIC的通道
CAN_ITConfig(CAN2,CAN_IT_FMP1,ENABLE);//打通CAN2_FIFO1到NVIC的通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组2(2位抢占优先级2位响应优先级)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=CAN1_RX0_IRQn;//选择CAN1_FIFO0接收中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化CAN1_FIFO0的NVIC
NVIC_InitStructure.NVIC_IRQChannel=CAN2_RX1_IRQn;//选择CAN2_FIFO1接收中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化CAN2_FIFO1的NVIC
}
/*
*函数简介:CAN1总线接收报文
*参数说明:报文存储数组
*返回类型:报文ID
*备注:默认8字节标准数据帧
*备注:没有接收到数据,直接退出,返回0
*/
uint32_t CAN_CAN1Receive(uint8_t *Data)
{
CanRxMsg RxMessage;
if(CAN_MessagePending(CAN1,CAN_FIFO0)==0)return 0;//没有接收到数据,直接退出
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);//读取数据
for(uint32_t i=0;i<8;i++)
Data[i]=RxMessage.Data[i];//储存数据
return RxMessage.StdId;//返回ID
}
/*
*函数简介:CAN2总线接收报文
*参数说明:报文存储数组
*返回类型:报文ID
*备注:默认8字节数据
*备注:没有接收到数据,直接退出,返回0
*/
uint32_t CAN_CAN2Receive(uint8_t *Data)
{
CanRxMsg RxMessage;
if(CAN_MessagePending(CAN2,CAN_FIFO1)==0)return 0;//没有接收到数据,直接退出
CAN_Receive(CAN2,CAN_FIFO1,&RxMessage);//读取数据
for(uint32_t i=0;i<8;i++)
Data[i]=RxMessage.Data[i];
return RxMessage.StdId;
}
/*
*函数简介:CAN1总线更改接收ID
*参数说明:接收ID
*返回类型:无
*备注:无
*/
void CAN_CAN1ChangeID(uint32_t ID)
{
CAN1->FMR |= 0x00000001;//配置CAN_FMR寄存器FINIT位进入初始化模式
CAN1->sFilterRegister[0].FR1 = ((uint32_t)0xFFE3<<16) | (ID<<5);//配置CAN_F0R1寄存器更改ID低位
CAN1->sFilterRegister[0].FR2 = ((uint32_t)0xFFE3<<16) | (ID<<5);//配置CAN_F0R2寄存器更改ID高位(16bits尺度下无高低位区别)
CAN1->FMR &= ~(0x00000001);//配置CAN_FMR寄存器FINIT位回到工作模式
}
/*
*函数简介:CAN2总线更改接收ID
*参数说明:接收ID
*返回类型:无
*备注:无
*/
void CAN_CAN2ChangeID(uint32_t ID)
{
CAN1->FMR |= 0x00000001;
CAN1->sFilterRegister[15].FR1 = ((uint32_t)0xFFE3<<16) | (ID<<5);
CAN1->sFilterRegister[15].FR2 = ((uint32_t)0xFFE3<<16) | (ID<<5);
CAN1->FMR &= ~(0x00000001);
}
/*
*函数简介:CAN接收ID列表复位
*参数说明:无
*返回类型:无
*备注:复位CAN_IDSelect,重新从CAN1的1号设备开始接收
*/
void CAN_CANIDReset(void)
{
CAN_IDSelect=0;
CAN_CAN1ChangeID(CAN_CAN1IDList[0][1]);
CAN_CAN2ChangeID(0x000);
}
/*
*函数简介:CAN接收获取裁判系统状态
*参数说明:无
*返回类型:无
*备注:跳转到接收底盘C板的回传数据,主要用于发射机构掉电时的CAN设备隔离
*/
void CAN_CAN_GetRefereeSystemData(void)
{
CAN_IDSelect=5;
CAN_CAN1ChangeID(0x000);
CAN_CAN2ChangeID(CAN_CAN2IDList[1][1]);
}
/*
*函数简介:CAN1_FIFO0接收中断函数
*参数说明:无
*返回类型:无
*备注:进入中断时关闭连接检测计时,离开中断时重新打开连接检测计时
*备注:某一设备掉线时,CAN_IDSelect会停留在当前设备在ID列表的索引
*备注:从掉线到重新连接时会重启遥控器
*/
void CAN1_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)==SET)//查询接收中断标志位
{
uint8_t Data[8];//接收数据
uint32_t ID=CAN_CAN1Receive(Data);//接收数据帧的ID
LinkCheck_OFF();//关闭连接检测定时
if(LinkCheck_ErrorID>=0 && LinkCheck_ErrorID<CAN_CAN1DeviceNumber)//接收的是掉线设备的数据
if(ID==CAN_CAN1IDList[LinkCheck_ErrorID][1])
{
LinkCheck_ErrorID=-1;//清除掉线设备
LinkCheck_Error=0;//回到正常连接状态
Warming_BuzzerClean();//清除蜂鸣器报警
}
if(CAN_CAN1IDList[CAN_IDSelect][0]==CAN_M3508)M3508_CANDataProcess(ID,Data);//处理M3508的数据
else if(CAN_CAN1IDList[CAN_IDSelect][0]==CAN_M2006)M2006_CANDataProcess(ID,Data);//处理M2006的数据
else GM6020_CANDataProcess(ID,Data);//处理GM6020的数据
CAN_IDSelect=(CAN_IDSelect+1)%CAN_DeviceNumber;//更换CAN总线ID切换选择位
if(CAN_IDSelect>=0 && CAN_IDSelect<CAN_CAN1DeviceNumber){CAN_CAN1ChangeID(CAN_CAN1IDList[CAN_IDSelect][1]);CAN_CAN2ChangeID(0x000);}//CAN1、CAN2更换接收ID
else{CAN_CAN1ChangeID(0x000);CAN_CAN2ChangeID(CAN_CAN2IDList[CAN_IDSelect-CAN_CAN1DeviceNumber][1]);}//设置接收ID为0规定为关闭接收
if(RefereeSystem_ShooterOpenFlag==1)//检测到发射机构上电添加CAN设备
{
RefereeSystem_ShooterOpenCounter++;
if(RefereeSystem_ShooterOpenCounter>=5000)//计次5000下等待发射机构设备启动
{
RefereeSystem_ShooterOpenCounter=0;
RefereeSystem_ShooterOpenFlag=0;//发射机构离开上电期间
CAN_CAN1DeviceNumber=4;//添加CAN设备
CAN_DeviceNumber=6;
}
}
LinkCheck_ON();//连接检测重新计时
CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);//清除CAN1的FIFO0接收中断标志位
}
}
/*
*函数简介:CAN2_FIFO1接收中断函数
*参数说明:无
*返回类型:无
*备注:进入中断时关闭连接检测计时,离开中断时重新打开连接检测计时
*备注:某一设备掉线时,CAN_IDSelect会停留在当前设备在ID列表的索引
*/
void CAN2_RX1_IRQHandler(void)
{
if(CAN_GetITStatus(CAN2,CAN_IT_FMP1)==SET)//查询接收中断标志位
{
uint8_t Data[8];//接收数据
uint32_t ID=CAN_CAN2Receive(Data);//接收数据帧的ID
LinkCheck_OFF();//关闭连接检测定时
if(LinkCheck_ErrorID>=CAN_CAN1DeviceNumber && LinkCheck_ErrorID<CAN_DeviceNumber)//接收的是掉线设备的数据
if(ID==CAN_CAN2IDList[LinkCheck_ErrorID-CAN_CAN1DeviceNumber][1])
{
LinkCheck_ErrorID=-1;//清除掉线设备
LinkCheck_Error=0;//回到正常连接状态
Warming_BuzzerClean();//清除蜂鸣器报警
}
if(CAN_CAN2IDList[CAN_IDSelect-CAN_CAN1DeviceNumber][0]==CAN_GM6020)GM6020_CANDataProcess(ID,Data);//处理6020的数据
else if(CAN_CAN2IDList[CAN_IDSelect-CAN_CAN1DeviceNumber][0]==CAN_RoboMasterC)CToC_CANDataProcess(ID,Data);//处理板间通讯
CAN_IDSelect=(CAN_IDSelect+1)%CAN_DeviceNumber;//更换CAN总线ID切换选择位
if(CAN_IDSelect>=0 && CAN_IDSelect<CAN_CAN1DeviceNumber){CAN_CAN1ChangeID(CAN_CAN1IDList[CAN_IDSelect][1]);CAN_CAN2ChangeID(0x000);}//CAN1、CAN2更换接收ID
else{CAN_CAN1ChangeID(0x000);CAN_CAN2ChangeID(CAN_CAN2IDList[CAN_IDSelect-CAN_CAN1DeviceNumber][1]);}//设置接收ID为0规定为关闭接收
if(RefereeSystem_ShooterOpenFlag==1)//检测到发射机构上电添加CAN设备
{
RefereeSystem_ShooterOpenCounter++;
if(RefereeSystem_ShooterOpenCounter>=5000)//计次5000下等待发射机构设备启动
{
RefereeSystem_ShooterOpenCounter=0;
RefereeSystem_ShooterOpenFlag=0;//发射机构离开上电期间
CAN_CAN1DeviceNumber=4;//添加CAN设备
CAN_DeviceNumber=6;
}
}
LinkCheck_ON();//连接检测重新计时
CAN_ClearITPendingBit(CAN2,CAN_IT_FMP1);//清除CAN2的FIFO1接收中断标志位
}
}

View File

@@ -0,0 +1,21 @@
#ifndef __CAN_H
#define __CAN_H
typedef enum
{
CAN_M3508=0,//M3508
CAN_M2006,//M2006
CAN_GM6020,//GM6020
CAN_RoboMasterC,//C板
}CAN_MotorModel;//CAN总线设备分类枚举
extern uint8_t CAN_CAN1DeviceNumber;//CAN1总线上设备数量
extern uint8_t CAN_CAN2DeviceNumber;//CAN2总线上设备数量
extern uint8_t CAN_DeviceNumber;//CAN总线上设备数量
extern int8_t CAN_IDSelect;//CAN总线上ID列表选择位
void CAN_CANInit(void);//CAN总线初始化
void CAN_CANIDReset(void);//CAN接收ID列表复位
void CAN_CAN_GetRefereeSystemData(void);//CAN接收获取裁判系统状态
#endif

View File

@@ -0,0 +1,44 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
/*
*函数简介:微秒级延时
*参数说明:延时时长,单位us
*返回类型:无
*备注:参数范围:0~4294967295
*/
void Delay_us(uint32_t us)
{
uint32_t temp;
SysTick->LOAD=us*21; //时间加载我们要延时n倍的us, 1us是一个fac_ua周期所以总共要延时的周期值为二者相乘最后送到Load中。
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开启使能位 开始倒数
do temp=SysTick->CTRL;
while((temp&0x01) && !(temp&(1<<16))); //用来判断 systick 定时器是否还处于开启状态然后在等待时间到达也就是数到0的时候,此时第十六位设置为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器使能位
SysTick->VAL=0x00; //清空计数器
}
/*
*函数简介:毫秒级延时
*参数说明:延时时长,单位ms
*返回类型:无
*备注:参数范围:0~4294967295
*/
void Delay_ms(uint32_t ms)
{
while(ms--)
Delay_us(1000);
}
/*
*函数简介:秒级延时
*参数说明:延时时长,单位s
*返回类型:无
*备注:参数范围:0~4294967295
*/
void Delay_s(uint32_t s)
{
while(s--)
Delay_ms(1000);
}

View File

@@ -0,0 +1,8 @@
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);//微秒级延时
void Delay_ms(uint32_t ms);//毫秒级延时
void Delay_s(uint32_t s);//秒级延时
#endif

View File

@@ -0,0 +1,440 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "MyI2C.h"
/*
*函数简介:软件I2C专用us延时
*参数说明:延时时长,单位1/21us
*返回类型:无
*备注:参数范围:0~4294967295
*/
void MyI2C_Delay_us(uint32_t us)
{
uint32_t temp;
SysTick->LOAD=us; //时间加载我们要延时n倍的us, 1us是一个fac_ua周期所以总共要延时的周期值为二者相乘最后送到Load中。
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开启使能位 开始倒数
do temp=SysTick->CTRL;
while((temp&0x01) && !(temp&(1<<16))); //用来判断 systick 定时器是否还处于开启状态然后在等待时间到达也就是数到0的时候,此时第十六位设置为1
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器使能位
SysTick->VAL=0x00; //清空计数器
}
/*
*函数简介:软件I2C写SCL电平
*参数说明:软件I2C配置结构体
*参数说明:高低电平,0-低电平 1-高电平
*返回类型:无
*备注:使用前需要先定义结构体并初始化
*备注:由于I2C速度较慢,在更改电平之后需要加入延时
*/
void MyI2C_SCL(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t x)
{
GPIO_WriteBit(MyI2C_InitStructure->MyI2C_SCL_GPIOx,MyI2C_InitStructure->MyI2C_SCL_Pin,(BitAction)(x));
MyI2C_Delay_us(1);//延时
}
/*
*函数简介:软件I2C写SDA电平
*参数说明:软件I2C配置结构体
*参数说明:高低电平,0-低电平 1-高电平
*返回类型:
*备注:使用前需要先定义结构体并初始化
*备注:由于I2C速度较慢,在更改电平之后需要加入延时
*/
void MyI2C_SDA(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t x)
{
GPIO_WriteBit(MyI2C_InitStructure->MyI2C_SDA_GPIOx,MyI2C_InitStructure->MyI2C_SDA_Pin,(BitAction)(x));
MyI2C_Delay_us(1);//延时
}
/*
*函数简介:软件I2C读SDA电平
*参数说明:软件I2C配置结构体
*返回类型:高低电平,0-低电平 1-高电平
*备注:使用前需要先定义结构体并初始化
*备注:由于I2C速度较慢,在电平更改之后需要加入延时,读取时也可以不加
*/
uint8_t MyI2C_Read_SDA(MyI2C_InitTypedef *MyI2C_InitStructure)
{
MyI2C_Delay_us(1);//延时
uint8_t SDA_Status=GPIO_ReadInputDataBit(MyI2C_InitStructure->MyI2C_SDA_GPIOx,MyI2C_InitStructure->MyI2C_SDA_Pin);
return SDA_Status;
}
/*
*函数简介:软件I2C初始化
*参数说明:软件I2C配置结构体
*返回类型:无
*备注:使用前需要先定义结构体并初始化
*/
void MyI2C_Init(MyI2C_InitTypedef *MyI2C_InitStructure)
{
RCC_AHB1PeriphClockCmd(MyI2C_InitStructure->MyI2C_SCL_RCC,ENABLE);//开启SCL时钟
RCC_AHB1PeriphClockCmd(MyI2C_InitStructure->MyI2C_SDA_RCC,ENABLE);//开启SDA时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;//开漏输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=MyI2C_InitStructure->MyI2C_SCL_Pin;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(MyI2C_InitStructure->MyI2C_SCL_GPIOx,&GPIO_InitStructure);//配置SCL
GPIO_InitStructure.GPIO_Pin=MyI2C_InitStructure->MyI2C_SDA_Pin;
GPIO_Init(MyI2C_InitStructure->MyI2C_SDA_GPIOx,&GPIO_InitStructure);//配置SDA
MyI2C_SCL(MyI2C_InitStructure,1);//初始化SCL
MyI2C_SDA(MyI2C_InitStructure,1);//初始化SDA
}
/*
*函数简介:软件I2C起始
*参数说明:软件I2C配置结构体
*返回类型:无
*I2C协议:
* SCL ~~~~/---\___
* SDA ~~/---\_____
*/
void MyI2C_Start(MyI2C_InitTypedef *MyI2C_InitStructure)
{
MyI2C_SDA(MyI2C_InitStructure,1);
MyI2C_SCL(MyI2C_InitStructure,1);//复位SCL和SDA
MyI2C_SDA(MyI2C_InitStructure,0);//起始
MyI2C_SCL(MyI2C_InitStructure,0);//准备接收数据
}
/*
*函数简介:软件I2C终止
*参数说明:软件I2C配置结构体
*返回类型:无
*I2C协议:
* SCL ____/-----
* SDA ~~\___/---
*/
void MyI2C_Stop(MyI2C_InitTypedef *MyI2C_InitStructure)
{
MyI2C_SDA(MyI2C_InitStructure,0);
MyI2C_SCL(MyI2C_InitStructure,1);//准备接收停止信号
MyI2C_SDA(MyI2C_InitStructure,1);//终止
}
/*
*函数简介:软件I2C产生应答
*参数说明:软件I2C配置结构体
*参数说明:是否应答,0-NAck非应答 1-Ack应答
*返回类型:无
*I2C协议:
* Ack:
* SCL____/-\___
* SDA~~\___/---
* NAck:
* SCL____/-\___
* SDA~~/-------
*/
void MyI2C_SendAck(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t AckBit)
{
MyI2C_SDA(MyI2C_InitStructure,!AckBit);//发送应答情况
MyI2C_SCL(MyI2C_InitStructure,1);//产生时钟
MyI2C_SCL(MyI2C_InitStructure,0);
MyI2C_SDA(MyI2C_InitStructure,1);//释放总线
}
/*
*函数简介:软件I2C接收应答
*参数说明:软件I2C配置结构体
*返回类型:是否应答,0-NAck非应答 1-Ack应答
*I2C协议:
* SCL ____/-\___
* SDA ~~/-|==|~~
* ( )从机
*/
uint8_t MyI2C_ReceiveAck(MyI2C_InitTypedef *MyI2C_InitStructure)
{
uint8_t AckBit;//应答标志位
MyI2C_SDA(MyI2C_InitStructure,1);//释放SDA总线
MyI2C_SCL(MyI2C_InitStructure,1);//提示从机发送Ack
AckBit=!MyI2C_Read_SDA(MyI2C_InitStructure);//接收应答
MyI2C_SCL(MyI2C_InitStructure,0);//置SCL为0,准备下一轮发送
return AckBit;//返回应答情况
}
/*
*函数简介:软件I2C发送一个8bits数据
*参数说明:软件I2C配置结构体
*参数说明:8bits发送数据
*返回类型:无
*I2C协议:
* SCL ____/-\___/-\___/-\___/-\___/-\___/-\___/-\___/-\___
* SDA ~~x=====x=====x=====x=====x=====x=====x=====x=====~~
*/
void MyI2C_Send8bits(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Byte)
{
for(uint8_t i=0;i<8;i++)
{
MyI2C_SDA(MyI2C_InitStructure,Byte&(0x80>>i));//发送数据每一位,高位先行
MyI2C_SCL(MyI2C_InitStructure,1);//产生时钟
MyI2C_SCL(MyI2C_InitStructure,0);
}
MyI2C_SDA(MyI2C_InitStructure,1);//释放SDA总线
}
/*
*函数简介:软件I2C读取一个8bits数据
*参数说明:软件I2C配置结构体
*返回类型:8bits接收数据
*I2C协议:
* SCL ____/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\___
* SDA ~~/-|==============================|~~
* ( )从机
*/
uint8_t MyI2C_Receive8bits(MyI2C_InitTypedef *MyI2C_InitStructure)
{
uint8_t Byte=0x00;
MyI2C_SDA(MyI2C_InitStructure,1);//释放SDA总线
for(uint8_t i=0;i<8;i++)//读取数据每一位,高位先行
{
MyI2C_SCL(MyI2C_InitStructure,1);//产生时钟
if(MyI2C_Read_SDA(MyI2C_InitStructure)){Byte|=(0x80>>i);}//读取SDA
MyI2C_SCL(MyI2C_InitStructure,0);
}
return Byte;
}
/*
*函数简介:软件I2C发送一个字节数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits发送数据
*返回类型:无
*备注:无
*/
void MyI2C_SendByte(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t Byte)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,Address<<1);//发送设备地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,Byte);//发送数据
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C发送数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:发送数据数组
*参数说明:发送数据数组长度
*返回类型:无
*备注:无
*/
void MyI2C_SendData(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t *Data,uint16_t Length)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,Address<<1);//发送设备地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
for(uint16_t i=0;i<Length;i++)
{
MyI2C_Send8bits(MyI2C_InitStructure,Data[i]);//发送数据
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
}
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C写寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits寄存器地址
*参数说明:8bits数据
*返回类型:无
*备注:无
*/
void MyI2C_WriteRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegAddress,uint8_t Data)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送从机地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,RegAddress);//发送寄存器地址
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,Data);//发送数据
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C接收一个字节数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*返回类型:8bits接收数据
*备注:无
*/
uint8_t MyI2C_ReceiveByte(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address)
{
uint8_t Byte=0;
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,(Address<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
Byte=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
return Byte;
}
/*
*函数简介:软件I2C接收数据
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:接收数据数组
*参数说明:接收数据数组长度
*返回类型:8bits接收数据
*备注:无
*/
void MyI2C_ReceiveData(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t *Data,uint16_t Length)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,(Address<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
for(uint16_t i=0;i<Length-1;i++)
{
Data[i]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,1);//发送Ack
}
Data[Length-1]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收最后一个数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C读寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits寄存器地址
*返回类型:8bits数据
*备注:无
*/
uint8_t MyI2C_ReadRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegAddress)
{
uint8_t Byte=0;
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送从机地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,RegAddress);//发送寄存器地址
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Start(MyI2C_InitStructure);//重复起始
MyI2C_Send8bits(MyI2C_InitStructure,(SlaveAddress<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
Byte=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
return Byte;
}
/*
*函数简介:软件I2C连续读寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits寄存器首地址
*参数说明:接收数据数组
*参数说明:接收数据数组长度
*返回类型:无
*备注:无
*/
void MyI2C_ContinuousReadRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegStartAddress,uint8_t *ReceiveData,uint16_t Length)
{
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送从机地址(写)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,RegStartAddress);//发送寄存器地址
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
MyI2C_Start(MyI2C_InitStructure);//重复起始
MyI2C_Send8bits(MyI2C_InitStructure,(SlaveAddress<<1) | 0x01);//发送设备地址(读)
while(MyI2C_ReceiveAck(MyI2C_InitStructure)!=1);//等待Ack应答
for(uint16_t i=0;i<Length-1;i++)
{
ReceiveData[i]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,1);//发送Ack
}
ReceiveData[Length-1]=MyI2C_Receive8bits(MyI2C_InitStructure);//接收最后一个数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
}
/*
*函数简介:软件I2C检测设备状态
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*返回类型:工作状态,0-设备不存在或异常工作 1-设备正常工作
*备注:无
*/
uint8_t MyI2C_CheckDevice(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address)
{
uint8_t WorkStatus;//工作标志位
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,Address<<1);//发送设备地址(写)
WorkStatus=MyI2C_ReceiveAck(MyI2C_InitStructure);//检测Ack应答
MyI2C_Stop(MyI2C_InitStructure);//终止
return WorkStatus;
}
/*
*函数简介:软件I2C查询Who Am I寄存器
*参数说明:软件I2C配置结构体
*参数说明:7bits从机地址
*参数说明:8bits Who Am I寄存器地址
*返回类型:Who Am I寄存器的值,0-设备不存在或异常工作 其他-返回寄存器值
*备注:无
*/
uint8_t MyI2C_CheckWhoAmI(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t WhoAmIAddress)
{
uint8_t WhoAmI;
MyI2C_Start(MyI2C_InitStructure);//起始
MyI2C_Send8bits(MyI2C_InitStructure,SlaveAddress<<1);//发送设备地址(写)
if(MyI2C_ReceiveAck(MyI2C_InitStructure)==0)return 0;//检测Ack应答
MyI2C_Send8bits(MyI2C_InitStructure,WhoAmIAddress);//发送寄存器地址
if(MyI2C_ReceiveAck(MyI2C_InitStructure)==0)return 0;//检测Ack应答
MyI2C_Start(MyI2C_InitStructure);//重复起始
MyI2C_Send8bits(MyI2C_InitStructure,(SlaveAddress<<1) | 0x01);//发送设备地址(读)
if(MyI2C_ReceiveAck(MyI2C_InitStructure)==0)return 0;//检测Ack应答
WhoAmI=MyI2C_Receive8bits(MyI2C_InitStructure);//接收数据
MyI2C_SendAck(MyI2C_InitStructure,0);//发送NAck
MyI2C_Stop(MyI2C_InitStructure);//终止
return WhoAmI;
}

View File

@@ -0,0 +1,35 @@
#ifndef __MYI2C_H
#define __MYI2C_H
typedef struct
{
uint32_t MyI2C_SCL_RCC;//SCL引脚时钟
GPIO_TypeDef *MyI2C_SCL_GPIOx;//SCL引脚的GPIO
uint32_t MyI2C_SCL_Pin;//SCL引脚的Pin号
uint32_t MyI2C_SDA_RCC;//SDA引脚时钟
GPIO_TypeDef *MyI2C_SDA_GPIOx;//SDA引脚的GPIO
uint32_t MyI2C_SDA_Pin;//SDA引脚的Pin号
}MyI2C_InitTypedef;//软件I2C配置结构体
void MyI2C_Init(MyI2C_InitTypedef *MyI2C_InitStructure);//软件I2C初始化
void MyI2C_Start(MyI2C_InitTypedef *MyI2C_InitStructure);//软件I2C起始
void MyI2C_Stop(MyI2C_InitTypedef *MyI2C_InitStructure);//软件I2C终止
void MyI2C_SendAck(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t AckBit);//软件I2C产生应答
uint8_t MyI2C_ReceiveAck(MyI2C_InitTypedef *MyI2C_InitStructure);//软件I2C接收应答
void MyI2C_Send8bits(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Byte);//软件I2C发送一个8bits数据
uint8_t MyI2C_Receive8bits(MyI2C_InitTypedef *MyI2C_InitStructure);//软件I2C读取一个8bits数据
void MyI2C_SendByte(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t Byte);//软件I2C发送一个字节数据
void MyI2C_SendData(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t *Data,uint16_t Length);//软件I2C发送数据
void MyI2C_WriteRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegAddress,uint8_t Data);//软件I2C写寄存器
uint8_t MyI2C_ReceiveByte(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address);//软件I2C接收一个字节数据
void MyI2C_ReceiveData(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address,uint8_t *Data,uint16_t Length);//软件I2C接收数据
uint8_t MyI2C_ReadRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegAddress);//软件I2C读寄存器
void MyI2C_ContinuousReadRegister(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t RegStartAddress,uint8_t *ReceiveData,uint16_t Length);//软件I2C连续读寄存器
uint8_t MyI2C_CheckDevice(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t Address);//软件I2C检测设备状态
uint8_t MyI2C_CheckWhoAmI(MyI2C_InitTypedef *MyI2C_InitStructure,uint8_t SlaveAddress,uint8_t WhoAmIAddress);//软件I2C查询Who Am I寄存器
#endif

View File

@@ -0,0 +1,72 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include "CAN.h"
/*==================== 定时器资源分配 ====================
TIM1(高级) ················PWM1~PWM4
TIM2 ················定时器
TIM3 ················激光
TIM4 ················蜂鸣器发声
TIM5 ················混色LED三色控制
TIM6(基本) ················PID闭环
TIM7(基本) ················遥控器连接检测
TIM8(高级) ················PWM5~PWM7
TIM9 ················
TIM10 ················陀螺仪加热电路
TIM11 ················陀螺仪姿态解算
TIM12 ················
TIM13 ················CAN总线设备连接检测
TIM14 ················
=============================================================*/
/*
*函数简介:TIM2定时器初始化
*参数说明:无
*返回类型:无
*备注:默认定时1ms
*备注:Freq=Sys_APB1TIM/(PSC+1)/(ARR+1)=84MHz/(PSC+1)/(ARR+1)
*/
void TIM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启时钟
TIM_InternalClockConfig(TIM2);//选择时基单元的时钟(此处为内部时钟),TIM_ITRxExternalClockConfig()接ITRx时钟,TIM_TIxExternalClockConfig()接TIx捕获通道时钟,TIM_ETRClockMode1Config()接ETR时钟(选择外部时钟模式1),TIM_ETRClockMode2Config()接ETR时钟(选择外部时钟模式2)
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//配置时基单元(配置参数)
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//配置时钟分频为1分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//配置计数器模式为向上计数
TIM_TimeBaseInitStructure.TIM_Period=200-1;//配置自动重装值ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=420-1;//配置分频值PSC,默认频率800Hz
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//配置重复计数单元的置为0
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//初始化TIM2
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除配置时基单元产生的中断标志位
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能更新中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组
NVIC_InitTypeDef NVIC_InitStructure;//配置NVIC配置参数
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//选择中断通道为TIM2
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//TIM2的抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//TIM2的响应优先级
NVIC_Init(&NVIC_InitStructure);//初始化NVIC
TIM_Cmd(TIM2,ENABLE);//启动定时器
}
/*
*函数简介:TIM2定时器更新中断函数
*参数说明:无
*返回类型:无
*备注:无
*/
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//检测TIM2更新
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
//函数体
}
}

View File

@@ -0,0 +1,6 @@
#ifndef __TIM_H
#define __TIM_H
void TIM_Init(void);//TIM2定时器初始化
#endif

View File

@@ -0,0 +1,541 @@
#include "stm32f4xx.h" // Device header
#include "stm32f4xx_conf.h"
#include <stdio.h>
#include <stdarg.h>
//重定向串口选择,选择哪个串口就把哪个取消注释
//#define UART1_Redirect//选择UART1重定向
#define UART2_Redirect//选择UART2重定向
uint8_t UART1_RxData;//接收数据缓存区
uint8_t UART1_RxFlag;//接收完成标志位
uint8_t UART2_RxData;//接收数据缓存区
uint8_t UART2_RxFlag;//接收完成标志位
/*
*函数简介:串口专用指数函数
*参数说明:底数x
*参数说明:指数y
*返回类型:x^y
*备注:x,y均为整数
*/
uint32_t USART_Pow(uint32_t x,uint32_t y)
{
uint32_t Result=1;
while(y--)
Result*=x;
return Result;
}
/*
*函数简介:UART1串口发送初始化
*参数说明:无
*返回类型:无
*备注:UART1为USART6,默认Tx引脚PG14
*/
void UART1_SendInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure);//初始化UART1-Tx(PG14)
GPIO_PinAFConfig(GPIOG,GPIO_PinSource14,GPIO_AF_USART6);//开启PG14的USART6复用模式
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Tx;//配置为发送模式
USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART6,&USART_InitStructure);//初始化USART6
USART_Cmd(USART6,ENABLE);//启动USART6
}
/*
*函数简介:UART1串口接收初始化
*参数说明:无
*返回类型:无
*备注:UART1为USART6,默认Rx引脚PG9
*/
void UART1_ReceiveInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure);//初始化UART1-Rx(PG9)
GPIO_PinAFConfig(GPIOG,GPIO_PinSource9,GPIO_AF_USART6);//开启PG9的USART6复用模式
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Rx;//配置为接收模式
USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART6,&USART_InitStructure);//初始化USART6
USART_ITConfig(USART6,USART_IT_RXNE,ENABLE);//打通USART6到NVIC的串口接收中断通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组2(2位抢占优先级2位响应优先级)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART6_IRQn;//选择USART6中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化USART6的NVIC
USART_Cmd(USART6,ENABLE);//启动USART6
}
/*
*函数简介:UART1串口初始化
*参数说明:无
*返回类型:无
*备注:UART1为USART6,默认Tx引脚PG14,Rx引脚PG9
*/
void UART1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure);//初始化UART1-Tx(PG14),UART1-Rx(PG9)
GPIO_PinAFConfig(GPIOG,GPIO_PinSource14,GPIO_AF_USART6);//开启PG14的USART6复用模式
GPIO_PinAFConfig(GPIOG,GPIO_PinSource9,GPIO_AF_USART6);//开启PG9的USART6复用模式
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;//配置为接发模式
USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART6,&USART_InitStructure);//初始化USART6
USART_ITConfig(USART6,USART_IT_RXNE,ENABLE);//打通USART6到NVIC的串口接收中断通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组2(2位抢占优先级2位响应优先级)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART6_IRQn;//选择USART6中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化USART6的NVIC
USART_Cmd(USART6,ENABLE);//启动USART6
}
/*
*函数简介:UART1发送一个字节
*参数说明:8bits数据
*返回类型:无
*备注:无
*/
void UART1_SendByte(uint8_t Byte)
{
USART_SendData(USART6,Byte);
while(USART_GetFlagStatus(USART6,USART_FLAG_TXE)==RESET);//等待发送完成
}
/*
*函数简介:UART1发送一个数组
*参数说明:8bits数组
*参数说明:数组长度
*返回类型:无
*备注:无
*/
void UART1_SendArray(uint8_t *Array,uint16_t Length)
{
for(uint16_t i=0;i<Length;i++)
UART1_SendByte(Array[i]);//依次发送数组的每一位
}
/*
*函数简介:UART1发送一个字符串
*参数说明:字符串
*返回类型:无
*备注:无
*/
void UART1_SendString(char *String)
{
for(uint8_t i=0;String[i]!='\0';i++)
UART1_SendByte(String[i]);//依次发送字符串的每一位
}
/*
*函数简介:UART1以文本形式发送一个数字
*参数说明:整型数字
*参数说明:数字长度(Length>=Number位数)
*返回类型:无
*备注:无
*/
void UART1_SendNumber(uint32_t Number,uint8_t Length)
{
for(uint8_t i=0;i<Length;i++)
UART1_SendByte(Number/USART_Pow(10,Length-i-1)%10+'0');//以文本形式发送数字每一位
}
#ifdef UART1_Redirect//选择UART1重定向
/*
*函数简介:重写fputc函数(重定向printf即移植printf)
*参数说明:无
*返回类型:无
*备注:看不懂
*备注:默认重定向UART1(即USART6),若想修改重定向串口,请更改最上方宏定义的注释
*/
int fputc(int ch,FILE *f)
{
USART6->DR=ch;
while(!(USART6->SR&(1<<7))){}
return ch;
}
/*
*函数简介:重写fgetc函数(重定向scanf即移植scanf)
*参数说明:无
*返回类型:无
*备注:看不懂
*备注:默认重定向UART1(即USART6),若想修改重定向串口,请更改最上方宏定义的注释
*/
int fgetc(FILE *stream)
{
while(!(USART6->SR&1<<5)){}
return USART6->DR;
}
#endif
/*
*函数简介:UART1的printf函数
*参数说明:无
*返回类型:无
*备注:等价printf函数,支持多串口
*备注:看不懂
*/
void UART1_Printf(char *format,...)
{
char Strings[100];
va_list arg;//定义参数列表变量arg
va_start(arg,format);//从format位置接收参数放在arg里
vsprintf(Strings,format,arg);//将格式化字符串打印到Strings
va_end(arg);//释放参数表arg
UART1_SendString(Strings);//发送字符串Strings
}
/*
*函数简介:UART1获取接收完成标志位
*参数说明:无
*返回类型:1-接收完成,0-接收未完成
*备注:接收完成会软件清零标志位
*/
uint8_t UART1_GetRxFlag(void)
{
if(UART1_RxFlag==1)
{
UART1_RxFlag=0;//复位
return 1;
}
return 0;
}
/*
*函数简介:UART2串口发送初始化
*参数说明:无
*返回类型:无
*备注:UART2为USART1,默认Tx引脚PA9
*/
void UART2_SendInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化UART2-Tx(PA9)
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//开启PA9的USART1复用模式
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Tx;//配置为发送模式
USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART1,&USART_InitStructure);//初始化USART1
USART_Cmd(USART1,ENABLE);//启动USART1
}
/*
*函数简介:UART2串口接收初始化
*参数说明:无
*返回类型:无
*备注:UART2为USART1,默认Rx引脚PB7
*/
void UART2_ReceiveInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化UART2-Rx(PB7)
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1);//开启PB7的USART1复用模式
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Rx;//配置为接收模式
USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART1,&USART_InitStructure);//初始化USART1
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//打通USART1到NVIC的串口接收中断通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组2(2位抢占优先级2位响应优先级)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//选择USART1中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化USART1的NVIC
USART_Cmd(USART1,ENABLE);//启动USART1
}
/*
*函数简介:UART2串口初始化
*参数说明:无
*返回类型:无
*备注:UART2为USART1,默认Tx引脚PA9,Rx引脚PB7
*/
void UART2_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//开启时钟
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//复用推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//默认上拉
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化UART2-Tx(PA9)
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化UART2-Rx(PB7)
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//开启PA9的USART1复用模式
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1);//开启PB7的USART1复用模式
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate=115200;//配置波特率115200
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//配置无硬件流控制
USART_InitStructure.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;//配置为接发模式
USART_InitStructure.USART_Parity=USART_Parity_No;//配置为无校验位
USART_InitStructure.USART_StopBits=USART_StopBits_1;//配置停止位为1
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//配置字长8bit
USART_Init(USART1,&USART_InitStructure);//初始化USART1
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//打通USART1到NVIC的串口接收中断通道
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC分组2(2位抢占优先级2位响应优先级)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//选择USART1中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级为1
NVIC_Init(&NVIC_InitStructure);//初始化USART1的NVIC
USART_Cmd(USART1,ENABLE);//启动USART1
}
/*
*函数简介:UART2发送一个字节
*参数说明:8bits数据
*返回类型:无
*备注:无
*/
void UART2_SendByte(uint8_t Byte)
{
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//等待发送完成
}
/*
*函数简介:UART2发送一个数组
*参数说明:8bits数组
*参数说明:数组长度
*返回类型:无
*备注:无
*/
void UART2_SendArray(uint8_t *Array,uint16_t Length)
{
for(uint16_t i=0;i<Length;i++)
UART2_SendByte(Array[i]);//依次发送数组的每一位
}
/*
*函数简介:UART2发送一个字符串
*参数说明:字符串
*返回类型:无
*备注:无
*/
void UART2_SendString(char *String)
{
for(uint8_t i=0;String[i]!='\0';i++)
UART2_SendByte(String[i]);//依次发送字符串的每一位
}
/*
*函数简介:UART2以文本形式发送一个数字
*参数说明:整型数字
*参数说明:数字长度(Length>=Number位数)
*返回类型:无
*备注:无
*/
void UART2_SendNumber(uint32_t Number,uint8_t Length)
{
for(uint8_t i=0;i<Length;i++)
UART2_SendByte(Number/USART_Pow(10,Length-i-1)%10+'0');//以文本形式发送数字每一位
}
#ifdef UART2_Redirect//选择UART2重定向
/*
*函数简介:重写fputc函数(重定向printf即移植printf)
*参数说明:无
*返回类型:无
*备注:看不懂
*备注:默认重定向UART1(即USART6),若想修改重定向串口,请更改最上方宏定义的注释
*/
int fputc(int ch,FILE *f)
{
USART1->DR=ch;
while(!(USART1->SR&(1<<7))){}
return ch;
}
/*
*函数简介:重写fgetc函数(重定向scanf即移植scanf)
*参数说明:无
*返回类型:无
*备注:看不懂
*备注:默认重定向UART1(即USART6),若想修改重定向串口,请更改最上方宏定义的注释
*/
int fgetc(FILE *stream)
{
while(!(USART1->SR&1<<5)){}
return USART1->DR;
}
#endif
/*
*函数简介:UART2的printf函数
*参数说明:无
*返回类型:无
*备注:等价printf函数,支持多串口
*备注:看不懂
*/
void UART2_Printf(char *format,...)
{
char Strings[100];
va_list arg;//定义参数列表变量arg
va_start(arg,format);//从format位置接收参数放在arg里
vsprintf(Strings,format,arg);//将格式化字符串打印到Strings
va_end(arg);//释放参数表arg
UART2_SendString(Strings);//发送字符串Strings
}
/*
*函数简介:UART2获取接收完成标志位
*参数说明:无
*返回类型:1-接收完成,0-接收未完成
*备注:接收完成会软件清零标志位
*/
uint8_t UART2_GetRxFlag(void)
{
if(UART2_RxFlag==1)
{
UART2_RxFlag=0;//复位
return 1;
}
return 0;
}
/*
*函数简介:UART1普通串口中断函数
*参数说明:无
*返回类型:无
*备注:接收完成置UART1_RxFlag为1,需软件清0
*/
/**************************************************
void USART6_IRQHandler(void)
{
if(USART_GetITStatus(USART6,USART_IT_RXNE)==SET)//查询接收中断标志位
{
UART1_RxData=USART_ReceiveData(USART6);//将数据存入缓存区
//函数体
UART1_RxFlag=1;//置接收完成标志位
}
USART_ClearITPendingBit(USART6,USART_IT_RXNE);//清除接收中断标志位
}
**************************************************/
/*
*函数简介:UART2普通串口中断函数
*参数说明:无
*返回类型:无
*备注:接收完成置UART2_RxFlag为1,需软件清0
*/
/**************************************************
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)//查询接收中断标志位
{
UART2_RxData=USART_ReceiveData(USART1);//将数据存入缓存区
//函数体
UART2_RxFlag=1;//置接收完成标志位
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除接收中断标志位
}
**************************************************/

View File

@@ -0,0 +1,28 @@
#ifndef __UART_H
#define __UART_H
extern uint8_t UART1_RxData;//接收数据缓存区
extern uint8_t UART1_RxFlag;//接收完成标志位
extern uint8_t UART2_RxData;//接收数据缓存区
extern uint8_t UART2_RxFlag;//接收完成标志位
void UART1_SendInit(void);//UART1串口发送初始化
void UART1_ReceiveInit(void);//UART1串口接收初始化
void UART1_Init(void);//UART1串口初始化
void UART1_SendByte(uint8_t Byte);//UART1发送一个字节
void UART1_SendArray(uint8_t *Array,uint16_t Length);//UART1发送一个数组
void UART1_SendString(char *String);//UART1发送一个字符串
void UART1_SendNumber(uint32_t Number,uint8_t Length);//UART1以文本形式发送一个数字
void UART1_Printf(char *format,...);//UART1的printf函数
uint8_t UART1_GetRxFlag(void);//UART1获取接收完成标志位
void UART2_SendInit(void);//UART2串口发送初始化
void UART2_ReceiveInit(void);//UART2串口接收初始化
void UART2_Init(void);//UART2串口初始化
void UART2_SendByte(uint8_t Byte);//UART2发送一个字节
void UART2_SendArray(uint8_t *Array,uint16_t Length);//UART2发送一个数组
void UART2_SendString(char *String);//UART2发送一个字符串
void UART2_SendNumber(uint32_t Number,uint8_t Length);//UART2以文本形式发送一个数字
void UART2_Printf(char *format,...);//UART2的printf函数
uint8_t UART2_GetRxFlag(void);//UART2获取接收完成标志位
#endif