Appmain.c
#include "cmsis_os2.h" // ::CMSIS:RTOS2
#include "main.h"
#include "gpio.h"
#include "usart.h"
#include "MotorControl.h"
#include "Appmain.h"
#include "canSendThread.h"
#include "spiwrite.h"
#include "appmain.h"
//uint16_t test_buf[256] __attribute__((at(0xC0000000))); //定义一个数组,该数组首地址为SDRAM首地址0xC0000000
uint64_t appThread_StackMemory[STACK_SIZE512] __attribute__((at(0x20028800)));
const osThreadAttr_t appmainthread_attr = { // 定义优先级
.stack_mem = &appThread_StackMemory[0],
.stack_size =sizeof(appThread_StackMemory)
};
osMessageQueueId_t canQSendMsgQ; // CAN 发送队列 2k
const osMessageQueueAttr_t canSendMsgQ_attr = {
.mq_mem = (void*)(0xc0013200),
.mq_size = 4096
};
osMessageQueueId_t encodeQSendMsgQ; // CAN 发送队列 2k
/*const osMessageQueueAttr_t encodeSendMsgQ_attr = {
.mq_mem = &encodeQMsg_StackMemory[0],
.mq_size = sizeof(encodeQMsg_StackMemory)
};*/
void app_main (void * arg);
/****************************************************************************
File name: motor.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: Init_MotorControlThreadThread
* 功能: 初始化电机控制线程 优先级 osPriorityAboveNormal
初始化队列
* 调用者: kernal
* 调用
* 入口参数:无
* 出口参数:0 成功 1 失败
****************************************************************************/
int Init_appMainThreadThread (void) {
canQSendMsgQ = osMessageQueueNew(16,sizeof(canReplyMsg_t),&canSendMsgQ_attr);
encodeQSendMsgQ = osMessageQueueNew(4,sizeof(Message_t),NULL);
osThreadNew (app_main, NULL, &appmainthread_attr);
return 0;
}
void app_main (void * arg) {
//Init_SpiWriteThread();
Init_canSendThread();
Init_MotorControlThreadThread ();
while(1)
{
//HAL_UART_Transmit(&huart3, (uint8_t *)"Hello World", 12,0xFFFF);
SETH(Run_Led_GPIO_Port,Run_Led_Pin);
osDelay(1000);
CLRL(Run_Led_GPIO_Port,Run_Led_Pin);
osDelay(1000);
}
}
Appmain.h
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : aPPmain.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APPMAIN_H
#define __APPMAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
#define CANMSGSEND_SIZE 2048
#define ENCODEMSGSEND_SIZE 512
typedef struct
{
uint8_t buf[126]; // 数据
uint16_t Length; // 长度
}Message_t;
typedef struct
{
uint16_t PackId;
uint8_t packData[6];
}canReplayDataMsg_t;
#pragma pack(1)
typedef struct
{
uint16_t heagPackId;
uint32_t packLength;
uint16_t packNum;
canReplayDataMsg_t data[5];
}canReplyMsg_t;
#pragma pack()
typedef struct
{
uint8_t device_id;
uint8_t cmd;
uint8_t data[22];
}canReplyMsgbuf_t;
typedef union
{
struct
{
uint8_t state;
uint8_t action;
uint8_t hole;
uint8_t doorhole;
uint32_t errCode;
} openLidstatus;
uint8_t buf[8];
}DevStatus_t;
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
extern osMessageQueueId_t canQSendMsgQ;
extern osMessageQueueId_t encodeQSendMsgQ;
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
extern void app_main (void * arg);
extern int Init_appMainThreadThread (void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
MotorControl.c
#include "cmsis_os2.h" // CMSIS RTOS header file
#include "MotorControl.h"
#include "gpio.h"
#include "usart.h"
#include "w25qxx.h"
#include "pcd4641.h"
#include "string.h"
#include "ResetAction.h"
#include "CentrifugeTubeAction.h"
#include "pcrTubeAction.h"
#include "appmain.h"
#include "BaseAction.h"
#include "discMotorAction.h"
#include <stdlib.h>
#define DEV_NO 5
#define RST_CMD 1
#define READ_STATUS_CMD 0
#define OPEN_CAP_CMD 2
#define CLOSE_CAP_CMD 3
#define MOVE_DISC_CMD 4
#define READ_VER_CMD 5
#define NODATA_REPALY 3
#define VER_DATA 17
#define CAN_ERROR_STATE 7
#define CAN_ERROR_PARAM 6
#define CAM_ERROR_COMMAND 4
#define ADDR_FLASH_SECTOR_22 ((uint32_t) 0x81c0000)
#define ADDR_FLASH_SECTOR_23 ((uint32_t) 0x81E0000)
#define ADDR_OUTFLASH_SECTOR ((uint32_t) 0x8200000)
#define FLASH_SECTOR_22USE ((uint32_t) ADDR_FLASH_SECTOR_22 - 4)
#define FLASH_SECTOR_23USE ((uint32_t) ADDR_OUTFLASH_SECTOR - 4)
#define FLASH_WRITE_MAXNUM ((uint32_t) 4096)
#define FLASH_DELAYTIME 50000
#define SECTOR_SIZE 0X20000
uint8_t verNo[VER_DATA] = {"V1.0.01rc20200605"};
osTimerId_t period10ms;
osThreadId_t MotorControl_Thread; // thread id
osSemaphoreId_t canRcvID; // Can 消息接受信号
osSemaphoreId_t uart3RcvID; // Can 消息接受信号
osEventFlagsId_t period10msEvt_id;
uint16_t canRcv_rd; // Can 读指针
uint16_t canRcvPackId; // Can 收到的包号
uint16_t canMsgRdPoint;
canRcv_Msg_t canMsg,*pCanRcvMsg;
uint32_t Timer_arg;
Motor_Action_t motorAction,*p_MotorAction;
Motor_ActionInfo_t *p_ExcuteAction;
uint8_t motorActionStep;
ActionType_e MotorMoveStatus;
uint8_t MotorMoveAxis;
uint16_t uart3Rcv_rd;
motor_Save_t saveMotorPara;
DiscAngle_Save_t saveDiscAnglePara;
uint8_t motorHasAction;
uint8_t motorActionStep;
uint32_t motorExtStatus[Max_Axis]; // 马达状态
uint8_t actionCreateStep;
int32_t currentPosition;
int32_t motorRstsStatus;
Motor_ActionInfo_t *pAction;
int8_t HasCentrifugeTube;
Message_t positionRcvMsg;
int32_t disc_Position;
uint32_t moveTime;
uint32_t canEcvCnt;
uint32_t canRcvPackCnt;
canReplyMsg_t canRepalyMsg;
DevStatus_t devStatus;
uint32_t statusWirteAdd;
uint16_t currentCapStatus;
uint64_t motor_StackMemory[STACK_SIZE2K] __attribute__((at(0x20028000)));
const osThreadAttr_t Motorthread_attr = {
.priority = osPriorityAboveNormal , // 定义优先级
.stack_mem = &motor_StackMemory[0],
.stack_size =sizeof(motor_StackMemory)
};
void MotorControlThread (void *argument); // thread function
void axis_stop(uint8_t axis_n);
const int32_t axisLimitDistance[Max_Axis] = {0,350,350,2200,0,3810,3810,350};
void Timer10msFunction(void *arg)
{
osEventFlagsSet(period10msEvt_id, 0x00000001U);
}
/****************************************************************************
File name: motor.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: Init_MotorControlThreadThread
* 功能: 初始化电机控制线程 优先级 osPriorityAboveNormal
初始化队列
* 调用者: kernal
* 调用
* 入口参数:无
* 出口参数:0 成功 1 失败
****************************************************************************/
int Init_MotorControlThreadThread (void) {
canRcvID = osSemaphoreNew(canBufLength,0,NULL);
if (canRcvID == NULL)
return -1;
uart3RcvID = osSemaphoreNew(uartMsgBufLength,0,NULL);
if (uart3RcvID == NULL)
return -1;
period10msEvt_id = osEventFlagsNew(NULL);
period10ms = osTimerNew(Timer10msFunction,osTimerPeriodic,&Timer_arg,NULL);
osTimerStart(period10ms,10);
MotorControl_Thread = osThreadNew (MotorControlThread, NULL, &Motorthread_attr);
if (!MotorControl_Thread) return(-1);
return(0);
}
void changeDevRunStatus(uint8_t action)
{
devStatus.openLidstatus.doorhole = 0;
devStatus.openLidstatus.hole = 0;
devStatus.openLidstatus.action = action;
devStatus.openLidstatus.state = 4;
}
void packCanReplayData(uint8_t cmd,uint8_t *pdata,uint8_t length)
{
canReplyMsgbuf_t pd;
uint8_t i,j,Fcs;
canReplayDataMsg_t *pCandata;
uint8_t *p;
canRepalyMsg.heagPackId = 0;// 起始包Id
canRepalyMsg.packLength = length+2;// 数据长度
canRepalyMsg.packNum = (canRepalyMsg.packLength+6)/6+1;// 命令包个数
pd.cmd = cmd;
pd.device_id = DEV_NO;
Fcs= pd.cmd ^ pd.device_id;
if (length>0 && pdata!=NULL)
{
for (i=0;i<length;i++)
{
pd.data[i] = pdata[i];
Fcs = Fcs^pd.data[i];
}
}
pd.data[canRepalyMsg.packLength-2] = Fcs;
p = (uint8_t *)(&pd);
for (i=0;i<canRepalyMsg.packNum;i++)
{
pCandata = &canRepalyMsg.data[i];
pCandata->PackId = i+1;
for (j=0;j<6;j++)
pCandata->packData[j] = *p++;
}
}
void packErrReplay(uint8_t cmd,uint32_t Errcode)
{
packCanReplayData(cmd,(uint8_t *)&Errcode,sizeof(Errcode));
}
uint16_t readuInt16(uint8_t *p)
{
return (uint16_t)p[0]+((uint16_t)p[1]<<8);
}
uint32_t readuInt32(uint8_t *p)
{
return (uint32_t)p[0]+((uint32_t)p[1]<<8)+((uint32_t)p[2]<<16)+((uint32_t)p[3]<<24);
}
/****************************************************************************
File name: motor.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: unSerilazePackData()
* 功能: 解包
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:2 成功 0 失败
****************************************************************************/
uint8_t unSerilazePackData()
{
//canPack *p;
uint8_t hole,doorhole;
canMsgPackData_t *p;
p = &canMsg.Data;
if (p->packdata[0] == DEV_NO)
{
switch (p->packdata[1])
{
case READ_STATUS_CMD:
packCanReplayData(READ_STATUS_CMD,(uint8_t *)&devStatus,sizeof(devStatus));
break;
case RST_CMD:
if (devStatus.openLidstatus.state ==1 || devStatus.openLidstatus.state ==2 || devStatus.openLidstatus.state ==0)
{
changeDevRunStatus(0x1);
CreateRstActionWithCapStatus();
motorHasAction = 1;
motorActionStep = 0;
packCanReplayData(RST_CMD,NULL,0);
}
else
packErrReplay(READ_STATUS_CMD|0x80,CAN_ERROR_STATE);
break;
case OPEN_CAP_CMD:
if (devStatus.openLidstatus.state !=1 && devStatus.openLidstatus.state !=2)
{
packErrReplay(OPEN_CAP_CMD|0x80,CAN_ERROR_STATE);
}
else
{
hole = (uint8_t)readuInt32(&p->packdata[2]);
if (hole>0 && hole<=16)
{
changeDevRunStatus(0x2);
packCanReplayData(OPEN_CAP_CMD,NULL,0);
if (hole%2==0)
createOpendPcrTubeAction(hole/2,Omit_Well);
else
createLoosedCentrifugeAction(hole/2+1,Omit_Well);
motorHasAction = 1;
motorActionStep = 0;
}
else
{
packErrReplay(OPEN_CAP_CMD|0x80,CAN_ERROR_PARAM);
}
}
break;
case CLOSE_CAP_CMD:
if (devStatus.openLidstatus.state !=1 && devStatus.openLidstatus.state !=2)
{
packErrReplay(CLOSE_CAP_CMD|0x80,CAN_ERROR_STATE);
}
else
{
hole = (uint8_t)readuInt16(&p->packdata[2]);
if (hole<=16)
{
changeDevRunStatus(0x3);
packCanReplayData(CLOSE_CAP_CMD,NULL,0);
if (hole == 0)
hole = devStatus.openLidstatus.hole;
doorhole = (uint8_t)readuInt16(&p->packdata[4]);
if (hole%2==0)
createClosedPcrTubeAction(hole/2,doorhole);
else
createTiedCentrifugeAction(hole/2+1,doorhole);
motorHasAction = 1;
motorActionStep = 0;
}
else
{
packErrReplay(CLOSE_CAP_CMD|0x80,CAN_ERROR_PARAM);
}
}
break;
case MOVE_DISC_CMD:
if (devStatus.openLidstatus.state !=1 && devStatus.openLidstatus.state !=2)
packErrReplay(MOVE_DISC_CMD|0x80,CAN_ERROR_STATE);
else
{
hole = (uint8_t)readuInt32(&p->packdata[2]);
if (hole>0 && hole<=16)
{
changeDevRunStatus(2);
discMotorMove(hole);
packCanReplayData(MOVE_DISC_CMD,NULL,0);
motorHasAction = 1;
motorActionStep = 0;
}
else
packErrReplay(READ_STATUS_CMD|0x80,CAN_ERROR_PARAM);
}
break;
case READ_VER_CMD:
packCanReplayData(READ_VER_CMD,verNo,sizeof(verNo));
break;
default:
packErrReplay(p->packdata[1]|0x80,CAM_ERROR_COMMAND);
break;
}
}
else
{
packErrReplay(READ_STATUS_CMD|0x80,CAN_ERROR_PARAM);
}
return 0;
}
uint32_t stm32FlashReadWord(uint32_t readAdd)
{
return *(uint32_t *) readAdd;
}
uint16_t stm32FlashReadHalfWord(uint32_t readAdd)
{
return *(uint32_t *) readAdd;
}
uint32_t eraseSector(uint32_t page)
{
uint32_t SectorError = 0;
FLASH_EraseInitTypeDef FlashEraseInit;
FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;
FlashEraseInit.Sector = page;
FlashEraseInit.NbSectors =1;
FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3;
HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError);
FLASH_WaitForLastOperation(FLASH_DELAYTIME);
return SectorError;
}
void CheckSector(uint32_t checkAdd,uint32_t NumToWrite,uint32_t page)
{
uint32_t endAddr;
endAddr = checkAdd+NumToWrite *4;
while (checkAdd<endAddr)
{
if (stm32FlashReadWord(checkAdd) != 0xffffffff)
{
eraseSector(page);
}
else
checkAdd = checkAdd+4;
}
}
void saveCurrentCapStatus(uint16_t capStatus)
{
HAL_FLASH_Unlock();
if (statusWirteAdd>ADDR_FLASH_SECTOR_22 && statusWirteAdd<ADDR_FLASH_SECTOR_23) // 写扇区23
{
if (statusWirteAdd>=(ADDR_FLASH_SECTOR_22+FLASH_WRITE_MAXNUM)) // 是否需要切换扇区
{
statusWirteAdd = ADDR_FLASH_SECTOR_23-2;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,statusWirteAdd,0x1); // 写擦除标记
FLASH_WaitForLastOperation(FLASH_DELAYTIME);
statusWirteAdd = ADDR_FLASH_SECTOR_23;
CheckSector(statusWirteAdd,SECTOR_SIZE/4,23); // 是否需要擦除 仅保护
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,FLASH_SECTOR_23USE,0x1); // 写运行标记
FLASH_WaitForLastOperation(FLASH_DELAYTIME);
}
}
else if (statusWirteAdd>ADDR_FLASH_SECTOR_23 && statusWirteAdd<ADDR_OUTFLASH_SECTOR)
{
if (statusWirteAdd>=(ADDR_FLASH_SECTOR_23+FLASH_WRITE_MAXNUM)) // 是否需要切换扇区
{
statusWirteAdd = ADDR_OUTFLASH_SECTOR-2;
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,statusWirteAdd,0x1); // 写擦除标记
FLASH_WaitForLastOperation(FLASH_DELAYTIME);
statusWirteAdd = ADDR_FLASH_SECTOR_22;
CheckSector(statusWirteAdd,SECTOR_SIZE/4,22); // 是否需要擦除 仅保护
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,FLASH_SECTOR_22USE,0x1); // 写运行标记
FLASH_WaitForLastOperation(FLASH_DELAYTIME);
}
}
FLASH_WaitForLastOperation(FLASH_DELAYTIME);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,statusWirteAdd,capStatus); // 写状态
statusWirteAdd=statusWirteAdd+2;
HAL_FLASH_Lock();
}
uint16_t getCurrentcapStatus()
{
uint16_t status = 0;
if (stm32FlashReadHalfWord(FLASH_SECTOR_22USE) == 0xffff && stm32FlashReadHalfWord(FLASH_SECTOR_23USE == 0xffff))
{
HAL_FLASH_Unlock();
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,FLASH_SECTOR_22USE,0x1);
HAL_FLASH_Lock();
statusWirteAdd=ADDR_FLASH_SECTOR_22;
}
else if (stm32FlashReadHalfWord(FLASH_SECTOR_22USE) == 1 && stm32FlashReadHalfWord(FLASH_SECTOR_22USE+2) == 0xffff)
{
statusWirteAdd=ADDR_FLASH_SECTOR_22;
while (stm32FlashReadHalfWord(statusWirteAdd)!=0xffff)
statusWirteAdd +=2;
if(statusWirteAdd == ADDR_FLASH_SECTOR_22) // 如果首地址 说明 最后一个状态未写入 尝试读取另一个扇区数据
status = stm32FlashReadHalfWord(ADDR_FLASH_SECTOR_23+FLASH_WRITE_MAXNUM-2);
else
status = stm32FlashReadHalfWord(statusWirteAdd-2);
if (stm32FlashReadHalfWord(FLASH_SECTOR_23USE) == 1 && stm32FlashReadHalfWord(FLASH_SECTOR_23USE+2) == 1)
{
HAL_FLASH_Unlock();
eraseSector(23);
HAL_FLASH_Lock();
}
}
else if (stm32FlashReadHalfWord(FLASH_SECTOR_23USE) == 1 && stm32FlashReadHalfWord(FLASH_SECTOR_23USE+2) == 0xffff)
{
statusWirteAdd=ADDR_FLASH_SECTOR_23;
while (stm32FlashReadHalfWord(statusWirteAdd)!=0xffff)
statusWirteAdd +=2;
if(statusWirteAdd == ADDR_FLASH_SECTOR_23) // 如果首地址 说明 最后一个状态未写入 尝试读取另一个扇区数据
status = stm32FlashReadHalfWord(ADDR_FLASH_SECTOR_22+FLASH_WRITE_MAXNUM-2);
else
status = stm32FlashReadHalfWord(statusWirteAdd-2);
if (stm32FlashReadHalfWord(FLASH_SECTOR_22USE) == 1 && stm32FlashReadHalfWord(FLASH_SECTOR_22USE+2) == 1)
{
HAL_FLASH_Unlock();
eraseSector(22);
HAL_FLASH_Lock();
}
}
else // 异常情况 重新擦除
{
if (stm32FlashReadHalfWord(FLASH_SECTOR_22USE) == 1
&& stm32FlashReadHalfWord(FLASH_SECTOR_22USE+2) == 1
&& stm32FlashReadHalfWord(FLASH_SECTOR_23USE) == 0xffff ) // 扇区满 但标记有问题 尝试读取另一个扇区数据
{
status = stm32FlashReadHalfWord(FLASH_SECTOR_22USE+FLASH_WRITE_MAXNUM-2);
}
if (stm32FlashReadHalfWord(FLASH_SECTOR_23USE) == 1
&& stm32FlashReadHalfWord(FLASH_SECTOR_23USE+2) == 1
&& stm32FlashReadHalfWord(FLASH_SECTOR_22USE) == 0xffff ) // 扇区满 但标记有问题 尝试读取另一个扇区数据
{
status = stm32FlashReadHalfWord(FLASH_SECTOR_23USE+FLASH_WRITE_MAXNUM-2);
}
HAL_FLASH_Unlock(); //全部复位
eraseSector(22);
eraseSector(23);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,FLASH_SECTOR_22USE,0x1); //写标志
HAL_FLASH_Lock();
statusWirteAdd=ADDR_FLASH_SECTOR_22;
}
return status;
}
/****************************************************************************
File name: motor.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: unPackCanMsg()
* 功能: 解包
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:2 成功 0 失败
****************************************************************************/
uint8_t unPackCanMsg()
{
canPack *p;
uint8_t i;
p = &canRcvData[canRcv_rd];
pCanRcvMsg = &canMsg;
canRcvPackId = (((uint16_t)p->packdata[1])<<8)+p->packdata[0];
// TODO 开缓冲判断stdID 由于目前只接受一个ID 不开缓冲
if (canRcvPackId == 0) // 第一个数据包
{
canMsgRdPoint = 0;
pCanRcvMsg->Head.packNum = (((uint16_t)p->packdata[7])<<8)+p->packdata[6]; //包个数
pCanRcvMsg->Head.packLength =(((uint16_t)p->packdata[5])<<24)+(((uint16_t)p->packdata[4])<<16)+
(((uint16_t)p->packdata[3])<<8)+p->packdata[2]; //包长度
canRcvPackCnt++;
}
else
{
if (canRcvPackId > pCanRcvMsg->Head.packNum-1)
return 0;
if (pCanRcvMsg->Head.packNum == 0)
return 0;
for (i=0;i<6;i++)
{
pCanRcvMsg->Data.packdata[(canRcvPackId-1)*6+i]=p->packdata[i+2];
}
if (canRcvPackId == pCanRcvMsg->Head.packNum-1)
{
unSerilazePackData();
osMessageQueuePut(canQSendMsgQ,&canRepalyMsg,0,0);
pCanRcvMsg->Head.packNum = 0;
canEcvCnt++;
return 1;
}
}
return 0;
}
/****************************************************************************
File name: motorControl.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: readUint16_3Byte()
* 功能: 读取 3字节 转换为short
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:2 成功 0 失败
****************************************************************************/
uint16_t readUint16_3Byte(uint8_t *rp)
{
uint16_t value;
value = (*rp-0x30)*100+(*(rp+1)-0x30)*10+*(rp+2)-0x30;
//p= p+3;
return value;
}
/****************************************************************************
File name: motorControl.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: readUint16_3Byte()
* 功能: 读取 3字节 转换为short
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:2 成功 0 失败
****************************************************************************/
uint16_t readUint16_4Byte(uint8_t *rp)
{
uint16_t value;
value = (*rp-0x30)*1000+(*(rp+1)-0x30)*100+(*(rp+2)-0x30)*10 + *(rp+3)-0x30;
//p= p+3;
return value;
}
/****************************************************************************
File name: motorControl.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: unPackUsart3Msg()
* 功能: 解包
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:2 成功 0 失败
****************************************************************************/
void unPackUsart3Msg()
{
uartPack *p_uart3Pack;
motor_Para_t *p;
uint8_t *rdCh;
uint32_t moveDistance;
uint8_t axis;
DiscAngle_Save_t *angleP;
//p = &saveMotorPara.DetalPara.para[0];
uint8_t i;
p_uart3Pack=&uart3_MsgRcvBuf[uart3Rcv_rd];
rdCh = &p_uart3Pack->packdata[1];
if (p_uart3Pack->packdata[0] == 'K') // 电机参数设定
{
for (i=0;i<Max_Axis;i++)
{
p = &saveMotorPara.DetalPara.para[i];
rdCh++; // Axis 信息忽略
p->LowSpeed = readUint16_3Byte(rdCh);
rdCh = rdCh +3;
p->HighSpeed = readUint16_3Byte(rdCh);
rdCh = rdCh +3;
p->AssessTime = readUint16_3Byte(rdCh);
rdCh = rdCh +3;
p->DistancePerCycle = readUint16_3Byte(rdCh);
rdCh = rdCh +3;
p->PluseNumPerCycle = (uint32_t)readUint16_3Byte(rdCh) * 200;
rdCh = rdCh + 3;
p->MoveDistace = readUint16_4Byte(rdCh);
rdCh = rdCh+4;
p->Roate_logic = POSTIVE_LOGIC;
p->LimitDistance = 0;
p->LimitDistance=axisLimitDistance[i];
}
saveMotorPara.DetalPara.flag = 1;
W25QXX_Write(saveMotorPara.buf,0,sizeof(saveMotorPara)*8+1);
}
else if (p_uart3Pack->packdata[0] == 'D') //圆盘角度设定
{
angleP = &saveDiscAnglePara;
angleP->AnglePara.centrifugeTubeAngle[0] = readUint16_4Byte(rdCh);
rdCh = rdCh+4;
angleP->AnglePara.pcrTubeAngle[0] = readUint16_4Byte(rdCh);
rdCh = rdCh+4;
angleP->AnglePara.discCentrifugeAngle = readUint16_4Byte(rdCh);
rdCh = rdCh+4;
angleP->AnglePara.discPcrAngle = readUint16_4Byte(rdCh);
angleP->AnglePara.flag = 1;
for (i=1;i<8;i++)
{
angleP->AnglePara.centrifugeTubeAngle[i] = angleP->AnglePara.centrifugeTubeAngle[i-1] + 450;
angleP->AnglePara.pcrTubeAngle[i] = angleP->AnglePara.pcrTubeAngle[i-1] +450;
}
W25QXX_Write(saveDiscAnglePara.buf,4096,sizeof(DiscAngle_Save_t));
}
else if (p_uart3Pack->packdata[0] == 'r')
{
CreateRstActionWithCapStatus();
motorHasAction = 1;
motorActionStep = 0;
}
else if (p_uart3Pack->packdata[0] == 'o')
{
//createTiedCentrifugeAction();
rdCh = &p_uart3Pack->packdata[1];
if (*rdCh == 0x31)
{
rdCh++;
createLoosedCentrifugeAction((*rdCh-0x30),Omit_Well);
}
else
{
rdCh++;
createOpendPcrTubeAction((*rdCh-0x30),Omit_Well);
}
motorHasAction = 1;
motorActionStep = 0;
}
else if (p_uart3Pack->packdata[0] == 'c')
{
if (*rdCh == 0x31)
{
rdCh++;
createTiedCentrifugeAction((*rdCh-0x30),Omit_Well);
}
else
{
rdCh++;
createClosedPcrTubeAction((*rdCh-0x30),Omit_Well);
}
//createLoosedCentrifugeAction();
motorHasAction = 1;
motorActionStep = 0;
}
else if (p_uart3Pack->packdata[0] == 't')
{
axis = *rdCh-0x31;
rdCh++;
moveDistance = readUint16_4Byte(rdCh);
if (axis<8)
{
if (axis == DISC_TURNING_AXIS)
{
osMessageQueueReset(encodeQSendMsgQ);
rstActtionList();
disRotation(moveDistance);
motorAction.Step = actionCreateStep;
motorHasAction = 1;
motorActionStep = 0;
}
else if (axis == CENTRIFUGE_CAP)
{
//SETM0();
//startCentrifugeTubeCapMotor();
rstActtionList();
loose_CentrifugeTubeCap();
motorAction.Step = actionCreateStep;
motorHasAction = 1;
motorActionStep = 0;
}
else
{
createMoveAxisTestModeAction(axis,moveDistance);
//createLoosedCentrifugeAction();
motorHasAction = 1;
motorActionStep = 0;
}
}
}
else if (p_uart3Pack->packdata[0] == 'a')
{
rstDiscMotorAction();
motorHasAction = 1;
motorActionStep = 0;
}
}
/****************************************************************************
File name: motorControl.C
Author: wangyong Version: 1.0 Date: 2015-01-19
* 名称:Excute_Motor_Action()
* 功能:读圆盘绝对位置
* 调用者:MotorControlThread
* 入口参数:无
* 出口参数:无
****************************************************************************/
void read_EncodePosition()
{
uint8_t ReadPositionCmd[4] = {0x44,0x30,0x31,0x0d};
HAL_UART_Transmit(&huart4,ReadPositionCmd,4,4);
}
void calcEncodePosition()
{
uint8_t i;
disc_Position = 0;
for(i=0;i<10;i++)
{
disc_Position*=10;
disc_Position += (uint32_t)(positionRcvMsg.buf[5+i] -0x30);
}
}
/****************************************************************************
File name: motorControl.C
Author: wangyong Version: 1.0 Date: 2015-01-19
* 名称:changeStep()
* 功能:序列器切换
* 调用者:Excute_Motor_Action()
* 入口参数:无
* 出口参数:0 运行结束 1 运行未结束
****************************************************************************/
uint8_t changeStep()
{
uint8_t i;
if (1 == p_MotorAction->RepeatFlag) // 有重复动作
{
if (motorActionStep<p_MotorAction->RepeatEnd-1)
{
motorActionStep++;
}
else
{
motorActionStep = p_MotorAction->RepeatStart-1;
for (i=motorActionStep;i<p_MotorAction->RepeatEnd;i++)
{
p_MotorAction->Action[i].ExcuteStatus = 0;
}
}
return 1;
} // if (1 == MotorActionptr->RepeatFlag)
else // 无重复动作
{
if (motorActionStep<p_MotorAction->Step-1) // 不是最后一节
{
motorActionStep++;
return 1;
}
else
{
return 0; // 运行结束
}
}
}
/****************************************************************************
File name: motorControl.C
Author: wangyong Version: 1.0 Date: 2015-01-19
* 名称:Excute_Motor_Action()
* 功能:马达动作序列执行
* 调用者:MotorControlThread
* 入口参数:无
* 出口参数:UCHAR 0-- 运行全部结束 1--运行未结束 2-- 开门状态
****************************************************************************/
uint8_t Excute_Motor_Action()
{
uint8_t excuteStatus;
int32_t pluse;
int32_t disc_MovePosition;
uint16_t writeCapStatus;
osStatus_t status;
uint32_t flags;
//uint16_t io;
motor_Para_t *pAxis;
p_MotorAction = &motorAction;
p_ExcuteAction = &motorAction.Action[motorActionStep];
MotorMoveAxis = p_ExcuteAction ->ActionAxis;
MotorMoveStatus = p_ExcuteAction ->status;
if (0 == p_ExcuteAction->ExcuteStatus) // 动作未执行完毕
{
p_ExcuteAction->ExcuteStatus = 1;
switch(MotorMoveStatus)
{
case STOP:
axis_stop_dec(MotorMoveAxis);
break;
case MOVE_LIMIT:
case MOVE_ORG:
axis_Move(MotorMoveAxis,p_ExcuteAction);
break;
case MOVE_POSITION:
pAxis = &saveMotorPara.DetalPara.para[MotorMoveAxis];
pluse = p_ExcuteAction->Postiontion *pAxis->PluseNumPerCycle/ pAxis->DistancePerCycle;
currentPosition = axis_read_pulse_count(MotorMoveAxis);
pluse -=currentPosition;
if (pluse>=0)
p_ExcuteAction->ControlMode = Liner_Nes_Pre_NoOrgSL;
else
p_ExcuteAction->ControlMode = Liner_Pos_Pre_NoOrgSL;
p_ExcuteAction->StartMode= Start_Motor_IntDisable_HighSpeed;
p_ExcuteAction->Postiontion = abs(pluse);
case MOVE_PLUSE:
axis_rmv_write(MotorMoveAxis,p_ExcuteAction->Postiontion);
axis_Move(MotorMoveAxis,p_ExcuteAction);
break;
case ENCODE_POSION_READ: // 编码电机数据读取
read_EncodePosition();
break;
case LOOSE:
SETM0();
startCentrifugeTubeCapMotor();
osDelay(2);
moveTime = 0;
break;
case TIED:
CLRM0();
startCentrifugeTubeCapMotor();
osDelay(2);
moveTime =0;
break;
case DISC_ROTATION:
pAxis = &saveMotorPara.DetalPara.para[MotorMoveAxis];
currentPosition = axis_read_pulse_count(MotorMoveAxis);
currentPosition = currentPosition%(pAxis->PluseNumPerCycle*3);
axis_pulse_count_write(MotorMoveAxis,currentPosition);
disc_MovePosition = p_ExcuteAction->Postiontion * (pAxis->PluseNumPerCycle*3)/3600;
if (disc_MovePosition<currentPosition)
pluse = pAxis->PluseNumPerCycle*3+disc_MovePosition - currentPosition;
else
pluse = disc_MovePosition - currentPosition;
/*if ((p_ExcuteAction->Postiontion)*5/200<disc_Position) // 计算旋转角度 精确到0.1
{
pluse = (ENCODEPLUSEPERCYCLE-disc_Position)*100+p_ExcuteAction->Postiontion*ENCODEPLUSEPERCYCLE/360;
}
else
{
pluse = p_ExcuteAction->Postiontion*ENCODEPLUSEPERCYCLE/360-disc_Position*100;
}*/
//pluse = pluse*pAxis->PluseNumPerCycle/(ENCODEPLUSEPERCYCLE*100);
p_ExcuteAction->ControlMode = Liner_Nes_Pre_NoOrgSL;
p_ExcuteAction->StartMode= Start_Motor_IntDisable_HighSpeed;
axis_rmv_write(MotorMoveAxis,pluse);
axis_Move(MotorMoveAxis,p_ExcuteAction);
break;
case CHANGESTATUS:
devStatus.openLidstatus.doorhole = p_ExcuteAction->doorhole;
devStatus.openLidstatus.hole = p_ExcuteAction->hole;
devStatus.openLidstatus.action = p_ExcuteAction->devStatus&0xf;
devStatus.openLidstatus.state = p_ExcuteAction->devStatus>>4;
break;
case WRITECAPSTATUS:
writeCapStatus = ((uint16_t)p_ExcuteAction->hole<<8) + p_ExcuteAction->doorhole;
currentCapStatus = writeCapStatus;
saveCurrentCapStatus(writeCapStatus);
break;
default:
;
}
return 1;
}
else
{
if (WAIT == MotorMoveStatus)
{
return 0;
}
else if (CHANGESTATUS == MotorMoveStatus )
{
excuteStatus = changeStep();
return excuteStatus;
}
else if (ENCODE_POSION_READ == MotorMoveStatus)
{
status = osMessageQueueGet(encodeQSendMsgQ,&positionRcvMsg,0U,0U);
if (osOK == status)
{
calcEncodePosition();
excuteStatus = changeStep();
return excuteStatus;
}
return 1;
}
else if (LOOSE == MotorMoveStatus || TIED == MotorMoveStatus)
{
//io = MOVE;
flags = osEventFlagsWait(period10msEvt_id, 0x00000001U, osFlagsWaitAny,0x1U);
if (flags == 0x00000001U)
moveTime ++;
if (!(MOVE) && moveTime>600)
{
excuteStatus = changeStep();
return excuteStatus;
}
return 1;
}
else
{
motorExtStatus[MotorMoveAxis]=axis_read_outstatus(MotorMoveAxis);
if (!(motorExtStatus[MotorMoveAxis] & 0x8)) // 运动 停止
{
p_ExcuteAction->ExcuteStatus = 2;
if (MOVE_ORG == MotorMoveStatus)
{
axis_pulse_count_rst(MotorMoveAxis);
}
excuteStatus = changeStep();
return excuteStatus;
/*if (1 == p_MotorAction->RepeatFlag) // 有重复动作
{
if (motorActionStep<p_MotorAction->RepeatEnd-1)
{
motorActionStep++;
}
else
{
motorActionStep = p_MotorAction->RepeatStart-1;
for (i=motorActionStep;i<p_MotorAction->RepeatEnd;i++)
{
p_MotorAction->Action[i].ExcuteStatus = 0;
}
}
return 1;
} // if (1 == MotorActionptr->RepeatFlag)
else // 无重复动作
{
if (motorActionStep<p_MotorAction->Step-1) // 不是最后一节
{
motorActionStep++;
return 1;
}
else
{
return 0; // 运行结束
}
}*/
}
else
{
return 1;
}
}
}
}
/****************************************************************************
File name: motor.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: void MotorControlThread (void *argument)
* 功能: 主线程 根据队列消息控制电机运行,完成开关盖动作
* 调用者: kernal
* 调用
* 入口参数:*argument
* 出口参数:无
****************************************************************************/
pcd4641_dev_t MotorChip;
void MotorControlThread (void *argument)
{
uint8_t TxData[3] = {"Ack"};
uint16_t i;
osStatus_t Status;
CAN_Start(); // 开启CAN
HAL_UART_Receive_IT(&huart3, (uint8_t *)&ustart3RdChar, 1); // 开Ustart3 中断
HAL_UART_Receive_IT(&huart4, (uint8_t *)&uart4RdChar, 1); // 开Ustart4 中断
//HAL_UART_Transmit(&huart4,TxData,8,10);
W25QXX_Init(); // 读电机参数
W25QXX_Read(saveMotorPara.buf,0,sizeof(motor_Para_t)*8+1);
uart3Rcv_rd = 0;
canEcvCnt = 0;
canRcvPackCnt = 0;
if (saveMotorPara.DetalPara.flag!=1)
{
for (i=0;i<8;i++)
{
saveMotorPara.DetalPara.para[i].LowSpeed = 60;
saveMotorPara.DetalPara.para[i].HighSpeed = 300;
}
W25QXX_Write(saveMotorPara.buf,0,sizeof(motor_Para_t)*8+1);
}
W25QXX_Read(saveDiscAnglePara.buf,4096,sizeof(DiscAngle_Save_t));
pcd4641_init(&MotorChip,&saveMotorPara);
read_EncodePosition();
SETALLMODE(); //CentrifugeTubeCapMotor M0 M1 M2 000
// currentCapStatus = getCurrentcapStatus();
//CLRALLMODE();
//CLRM0();
//CLRSTART();
//startCentrifugeTubeCapMotor();
//axis_SearchOrg(0,0);
/*axis_stop(1);
axis_rmv_write(1,100000);
pcd4641_write_command_regs(1,0x44,NULL,0);
pcd4641_write_command_regs(1,0X15,NULL,0);
axis_stop(1);
axis_pulse_count_rst(6);
k = axis_read_pulse_count(6);
axis_rmv_write(6,100);
osDelay(1000);
k = axis_read_pulse_count(6);*/
//W25QXX_Erase_Sector(2);
//W25QXX_Erase_Sector(3);
motorHasAction = 0;
memset(&devStatus,0,sizeof(devStatus));
devStatus.openLidstatus.action = 0;
//CreatRstAction();
//motorHasAction = 1;
while (1)
{
//TODO 添加时基 5ms
if (motorHasAction)
motorHasAction = Excute_Motor_Action();
Status = osSemaphoreAcquire(canRcvID,1U);
if (osOK == Status) // 接收到Can 数据
{
unPackCanMsg();
//CAN_SendData(0x100,(uint8_t *)"CAN RCV",7);
canRcv_rd++;
canRcv_rd%=canBufLength;
}
Status = osSemaphoreAcquire(uart3RcvID,1U);
if (osOK == Status) // 接收到Pc数据
{
unPackUsart3Msg();
uart3Rcv_rd++;
uart3Rcv_rd%=uartMsgBufLength;
HAL_UART_Transmit(&huart3,TxData,3,1); // send Ack
}
osDelay(1);
/*
SETH(Status_Led_GPIO_Port,Status_Led_Pin);
osDelay(1000);
//CLRL(Status_Led_GPIO_Port,Status_Led_Pin);
//osDelay(1000); // suspend thread
CAN_SendData(0x600,TxData,8);*/
}
}
MotorControl.h
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : aPPmain.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MOTORCONTROL_H
#define __MOTORCONTROL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "cmsis_os2.h"
#include "sys_stru.h"
/* Private includes ----------------------------------------------------------*/
#include "can.h"
#define CanPackDataLength 1024
#define MaxActionStep 100
/* USER CODE BEGIN Includes */
typedef struct
{
uint32_t packstdID;
uint32_t packLength;
uint16_t packNum;
} canMsgPackHead_t;
typedef struct
{
uint8_t packdata[CanPackDataLength];
} canMsgPackData_t;
typedef struct
{
canMsgPackHead_t Head;
canMsgPackData_t Data;
} canRcv_Msg_t;
typedef struct
{
Motor_ActionInfo_t Action[MaxActionStep];
uint8_t Step; // 动作步骤数
uint8_t RepeatFlag; // 0- 单次 1--重复
uint8_t RepeatEnd;
uint8_t RepeatStart;
} Motor_Action_t;
extern Motor_Action_t motorAction,*p_MotorAction;
extern uint8_t actionCreateStep;
extern int32_t motorRstsStatus;
extern Motor_ActionInfo_t *pAction;
extern int8_t HasCentrifugeTube;
extern void MotorControlThread (void *argument); // thread function
extern osThreadId_t MotorControl_Thread; // thread id
extern int Init_MotorControlThreadThread (void);
extern motor_Save_t saveMotorPara;
extern DiscAngle_Save_t saveDiscAnglePara;
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
//extern void app_main (void * arg);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
canSendThread.c
#include "cmsis_os2.h" // CMSIS RTOS header file
#include "main.h"
#include "Appmain.h"
#include "can.h"
void canSendThread (void *argument); // thread function
osThreadId_t canSend_ThreadId; // thread id
uint64_t canSend_StackMemory[STACK_SIZE512] __attribute__((at(0x20028a00)));
uint32_t canSendCnt;
const osThreadAttr_t canSendthread_attr = {
.priority = osPriorityNormal , // 定义优先级
.stack_mem = &canSend_StackMemory[0],
.stack_size =sizeof(canSend_StackMemory)
};
int Init_canSendThread (void) {
canSend_ThreadId = osThreadNew (canSendThread, NULL, &canSendthread_attr);
if (!canSend_ThreadId) return(-1);
return(0);
}
void canSendThread (void *argument) {
canReplyMsg_t rcvMsg;
osStatus_t status;
canSendCnt = 0;
while (1) {
status = osMessageQueueGet(canQSendMsgQ,&rcvMsg,NULL,1u);
if (osOK == status)
{
CAN_SendData(0x91,(uint8_t *)&rcvMsg,rcvMsg.packNum*8);
canSendCnt ++;
}
osDelay(1);
}
}
CRC16_ModbusRTU.c
#include "cmsis_os2.h"
const uint16_t polynom = 0xA001;
uint16_t crc16_ModBusRtu(uint8_t *ptr, uint16_t len)
{
uint8_t i;
uint16_t crc = 0xffff;
if (len == 0)
{
return 0xffff;
}
while (len--)
{
crc ^= *ptr;
for (i = 0; i<8; i++)
{
if (crc & 1)
{
crc >>= 1;
crc ^= polynom;
}
else
{
crc >>= 1;
}
}
ptr++;
}
return (crc);
}
ResetAction.c
#include "cmsis_os2.h"
#include "pcd4641.h"
#include "string.h"
#include "MotorControl.h"
#include "BaseAction.h"
extern uint16_t currentCapStatus;
void clampCentrifugeMotorMoveOutOrg()
{
// 初始化离心管 夹紧电机·
// 如果不在原点 表示有试管
pAction[actionCreateStep].ActionAxis = CLAMP_CENTRIFUGE_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = 75500;
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void clampPcrMotorMoveOutOrg()
{
// 初始化离心管 夹紧电机·
// 如果不在原点 表示有试管
pAction[actionCreateStep].ActionAxis = CLAMP_PCRTUBE_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = 75500;
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void rstCentrifugeTube()
{
int32_t pluse;
motor_Para_t *axisP;
HasCentrifugeTube = 0;
axisP = &saveMotorPara.DetalPara.para[0];
motorRstsStatus = axis_read_outstatus(CENTRIFUGE_Z_AXIS); // Z轴是否在ORG
pluse = (-1) * (int32_t)axisP[CENTRIFUGE_Z_AXIS].LimitDistance*(int32_t)axisP[CENTRIFUGE_Z_AXIS].PluseNumPerCycle/
(int32_t) axisP[CENTRIFUGE_Z_AXIS].DistancePerCycle;
z_CentrifugeTubeMotorMovePluse(pluse); // 先运动到极限位
if (motorRstsStatus & SORG) // 电机在原点
{
//z_CentrifugeTubeMotorMovePluse(-7500); // 移出原点位置
motorRstsStatus = axis_read_outstatus(CLAMP_CENTRIFUGE_AXIS);
if (!(motorRstsStatus & SORG)) // 表明夹爪上有离心管盖
{
// 归零
z_CentrifugeTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
// 固定离心管
fixCentrifugeMotorMovePosition((int32_t)axisP[FIXED_CENTRIFUGE_AXIS].MoveDistace);
// 运动到旋紧位置
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
// todo 旋紧离心管盖
tied_CentrifugeTubeCap();
}
else
{
clampCentrifugeMotorMoveOutOrg();
}
}
else
{
// 夹爪在零位 Z处于运动中或z已到位 但夹爪未夹紧
// 夹爪不在零位 z已到位 但夹爪夹紧或运行到夹紧态 此时应松开夹爪
motorRstsStatus = axis_read_outstatus(CLAMP_CENTRIFUGE_AXIS);
if (!(motorRstsStatus & SORG)) // 表明夹爪上有离心管盖 且Z不在零位
{
// todo松离心管盖
loose_CentrifugeTubeCap();
// 归零
z_CentrifugeTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
// 固定离心管
fixCentrifugeMotorMovePosition((int32_t)axisP[FIXED_CENTRIFUGE_AXIS].MoveDistace);
// Z运行到旋紧位
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
// todo 旋紧离心管盖
tied_CentrifugeTubeCap();
}
else
{
clampCentrifugeMotorMoveOutOrg();
}
}
// 松开离心管夹爪
releaseCentrifugeTubeClamp();
//Z 归零
z_CentrifugeTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
// 测试夹爪不在位情况
//clampCentrifugeMotorMoveOutOrg();
// 测试Postion 移动情况
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
z_CentrifugeTubeMotorMovePosition(0);
}
void rstPcrTube()
{
motor_Para_t *axisP;
HasCentrifugeTube = 0;
axisP = &saveMotorPara.DetalPara.para[0];
z_PcrTubeMotorTurnZero();
motorRstsStatus = axis_read_outstatus(CLAMP_PCRTUBE_AXIS);
if (!(motorRstsStatus & SORG)) // 表明夹爪上有PCR管盖
{
// 释放pcr管
unFixPcrTube();
// 固定pcr管
fixPcrTubeMotorMovePosition((int32_t)axisP[FIXED_PCRTUBE_AXIS].MoveDistace);
// z 运动到固定位 盖盖
z_PcrTubeMotorMovePosition((int32_t)axisP[PCR_Z_AXIS].MoveDistace);
// 松开夹爪
releasePcrTubeClamp();
// z 归零
z_PcrTubeMotorTurnZero();
}
else
{
// 复位夹爪
clampPcrMotorMoveOutOrg();
releasePcrTubeClamp();
}
// 释放Pcr管
unFixPcrTube();
}
void rstDisc()
{
motor_Para_t *axisP;
axisP = &saveMotorPara.DetalPara.para[DISC_TURNING_AXIS];
motorRstsStatus = axis_read_outstatus(DISC_TURNING_AXIS);
if (motorRstsStatus & SORG)
{
discMotorMovePluse(axisP->PluseNumPerCycle*3/2);// 10度
}
discMotorTunrZero();
discMotorMovePluse(axisP->PluseNumPerCycle*3/2);// 10度
discMotorTunrZero();
}
/****************************************************************************
File name: imotorControl.C
Author: wangyong Version: 1.0 Date: 2015-01-19
* 名称:CreatRstAction()
* 功能:复位动作
* 调用者:MotorControlThread
* 入口参数:无
* 出口参数:无
****************************************************************************/
void CreatRstAction()
{
rstActtionList();
//changeStatus(0,0,0x41); // 更新状态
//axis_read_msts(1);
// 复位离心管组电机
rstCentrifugeTube();
// 复位PCR
rstPcrTube();
//复位圆盘
rstDisc();
changeStatus(0,0,0x10);
motorAction.Step = actionCreateStep;
//motorActionStep = 0;
}
void CreateRstActionWithCapStatus()
{
uint8_t hole,doorhole;
//uint16_t roateAngle;
motor_Para_t *axisP;
uint8_t well;
axisP = &saveMotorPara.DetalPara.para[0];
rstActtionList();
well = (currentCapStatus & 0xff00)>>8;
doorhole = currentCapStatus &0xff;
if (well >0 && well <=16) // 有盖子在夹爪上
{
if (doorhole!=0) //圆盘已转出 此时 盖子在夹爪上 且已归零
{
// 释放Pcr管
unFixPcrTube();
//释放离心管
unFixCentrifuge();
//复位圆盘
rstDisc();
// 管子旋转到位
if (hole%2 == 0)
{
hole = well/2;
disRotation(saveDiscAnglePara.AnglePara.pcrTubeAngle[hole-1]);
}
else
{
hole = (well-1)/2+1;
disRotation(saveDiscAnglePara.AnglePara.centrifugeTubeAngle[hole-1]);
}
SaveCapStatus(hole,0);
}
if (well %2!=0) // 离心管在夹爪上
{
if (doorhole==0) //圆盘未转出 有可能处于松盖的状态
{
// todo松离心管盖
loose_CentrifugeTubeCap();
}
// 归零
z_CentrifugeTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
// 固定离心管
fixCentrifugeMotorMovePosition((int32_t)axisP[FIXED_CENTRIFUGE_AXIS].MoveDistace);
// 运动到旋紧位置
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
// todo 旋紧离心管盖
tied_CentrifugeTubeCap();
SaveCapStatus(0,0);
// 松开离心管夹爪
releaseCentrifugeTubeClamp();
// 归零
z_CentrifugeTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
// 复位pcr夹爪
motorRstsStatus = axis_read_outstatus(CLAMP_PCRTUBE_AXIS);
if (motorRstsStatus & SORG)
clampPcrMotorMoveOutOrg();
releasePcrTubeClamp();
// 释放pcr管
unFixPcrTube();
// z Pcr 归零
z_PcrTubeMotorTurnZero();
}
else
{
// z 归零
z_PcrTubeMotorTurnZero();
// 释放pcr管
unFixPcrTube();
// 固定pcr管
fixPcrTubeMotorMovePosition((int32_t)axisP[FIXED_PCRTUBE_AXIS].MoveDistace);
// z 运动到固定位 盖盖
z_PcrTubeMotorMovePosition((int32_t)axisP[PCR_Z_AXIS].MoveDistace);
// 松开夹爪
releasePcrTubeClamp();
SaveCapStatus(0,0);
// z 归零
z_PcrTubeMotorTurnZero();
// 释放pcr管
unFixPcrTube();
// 复位离心管夹爪
motorRstsStatus = axis_read_outstatus(CLAMP_CENTRIFUGE_AXIS);
if (motorRstsStatus & SORG)
clampCentrifugeMotorMoveOutOrg();
releaseCentrifugeTubeClamp();
//Z 离心管归零
z_CentrifugeTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
}
}
else
{
// 复位离心管夹爪
motorRstsStatus = axis_read_outstatus(CLAMP_CENTRIFUGE_AXIS);
if (motorRstsStatus & SORG)
clampCentrifugeMotorMoveOutOrg();
releaseCentrifugeTubeClamp();
//Z 离心管归零
z_CentrifugeTubeMotorTurnZero();
// 复位pcr夹爪
motorRstsStatus = axis_read_outstatus(CLAMP_PCRTUBE_AXIS);
if (motorRstsStatus & SORG)
clampPcrMotorMoveOutOrg();
releasePcrTubeClamp();
// z 归零
z_PcrTubeMotorTurnZero();
//释放离心管
unFixCentrifuge();
// 释放pcr管
unFixPcrTube();
}
//复位圆盘
rstDisc();
changeStatus(0,0,0x10);
SaveCapStatus(0,0);
motorAction.Step = actionCreateStep;
}
BaseAction.c
#include "cmsis_os2.h"
#include "pcd4641.h"
#include "string.h"
#include "MotorControl.h"
#include "Gpio.h"
#include <stdlib.h>
void z_CentrifugeTubeMotorMovePluse(int32_t pluse);
void Z_PcrTubeMotorMovePluse(int32_t pluse);
void rstActtionList(void);
void z_CentrifugeTubeMotorTurnZero()
{
int32_t pluse;
motor_Para_t *axisP;
axisP = &saveMotorPara.DetalPara.para[CENTRIFUGE_Z_AXIS];
// 由于 Z 轴搜寻原点向下 但只有上限位 为统一搜寻方向 搜寻原点 先向上到极限位
pluse = (-1) * (int32_t)axisP->LimitDistance*(int32_t)axisP->PluseNumPerCycle/
(int32_t) axisP->DistancePerCycle;
z_CentrifugeTubeMotorMovePluse(pluse); // 先运动到极限位
pAction[actionCreateStep].ActionAxis = CENTRIFUGE_Z_AXIS ;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Nes_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void z_CentrifugeTubeMotorMovePluse(int32_t pluse)
{
pAction[actionCreateStep].ActionAxis = CENTRIFUGE_Z_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = abs(pluse);
if (pluse>=0)
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
else
pAction[actionCreateStep].ControlMode = Liner_Pos_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void z_CentrifugeTubeMotorMovePosition(int32_t position)
{
pAction[actionCreateStep].ActionAxis = CENTRIFUGE_Z_AXIS;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
actionCreateStep++;
}
void releaseCentrifugeTubeClamp()
{
pAction[actionCreateStep].ActionAxis = CLAMP_CENTRIFUGE_AXIS;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Pos_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void centrifugeTubeClampMotorMovePosition(int32_t position)
{
pAction[actionCreateStep].ActionAxis = CLAMP_CENTRIFUGE_AXIS;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void fixCentrifugeMotorMovePlus(int32_t pluse)
{
pAction[actionCreateStep].ActionAxis = FIXED_CENTRIFUGE_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = abs(pluse);
if (pluse>=0)
pAction[actionCreateStep].ControlMode = Liner_Pos_Pre_NoOrgSL;
else
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void fixCentrifugeMotorMovePosition(int32_t position)
{
pAction[actionCreateStep].ActionAxis = FIXED_CENTRIFUGE_AXIS;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void unFixCentrifuge()
{
pAction[actionCreateStep].ActionAxis = FIXED_CENTRIFUGE_AXIS ;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Pos_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void fixPcrTubeMotorMovePosition(int32_t position)
{
pAction[actionCreateStep].ActionAxis = FIXED_PCRTUBE_AXIS;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void unFixPcrTube()
{
pAction[actionCreateStep].ActionAxis = FIXED_PCRTUBE_AXIS ;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Pos_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void z_PcrTubeMotorTurnZero()
{
int32_t pluse;
motor_Para_t *axisP;
axisP = &saveMotorPara.DetalPara.para[PCR_Z_AXIS];
// 由于 Z 轴搜寻原点向下 但只有上限位 为统一搜寻方向 搜寻原点 先向上到极限位
pluse = (-1) * (int32_t)axisP->LimitDistance*(int32_t)axisP->PluseNumPerCycle/
(int32_t) axisP->DistancePerCycle;
Z_PcrTubeMotorMovePluse(pluse); // 先运动到极限位
pAction[actionCreateStep].ActionAxis = PCR_Z_AXIS ;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Nes_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void Z_PcrTubeMotorMovePluse(int32_t pluse)
{
pAction[actionCreateStep].ActionAxis = PCR_Z_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = abs(pluse);
if (pluse>=0)
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
else
pAction[actionCreateStep].ControlMode = Liner_Pos_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void z_PcrTubeMotorMovePosition(int32_t position)
{
pAction[actionCreateStep].ActionAxis = PCR_Z_AXIS;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
actionCreateStep++;
}
void releasePcrTubeClamp()
{
pAction[actionCreateStep].ActionAxis = CLAMP_PCRTUBE_AXIS;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Pos_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void pcrTubeClampMotorMovePlus(int32_t pluse)
{
pAction[actionCreateStep].ActionAxis = CLAMP_PCRTUBE_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = abs(pluse);
if (pluse>=0)
pAction[actionCreateStep].ControlMode = Liner_Pos_Pre_NoOrgSL;
else
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void pcrTubeClampMotorMovePosition(int32_t position)
{
pAction[actionCreateStep].ActionAxis = CLAMP_PCRTUBE_AXIS;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void tied_CentrifugeTubeCap()
{
pAction[actionCreateStep].ActionAxis = CENTRIFUGE_CAP;
pAction[actionCreateStep].status = TIED;
actionCreateStep++;
}
void loose_CentrifugeTubeCap()
{
pAction[actionCreateStep].ActionAxis = CENTRIFUGE_CAP;
pAction[actionCreateStep].status = LOOSE;
actionCreateStep++;
}
void disRotation(int32_t angle)
{
/*pAction[actionCreateStep].ActionAxis = DISC_TURNING_AXIS;
pAction[actionCreateStep].status = ENCODE_POSION_READ;
actionCreateStep++;*/
pAction[actionCreateStep].ActionAxis = DISC_TURNING_AXIS;
pAction[actionCreateStep].status = DISC_ROTATION;
pAction[actionCreateStep].Postiontion = angle;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void createMoveAxisTestModeAction(uint8_t axis,uint32_t position)
{
rstActtionList();
pAction[actionCreateStep].ActionAxis = axis;
pAction[actionCreateStep].status = MOVE_POSITION;
pAction[actionCreateStep].Postiontion = position;
actionCreateStep++;
motorAction.Step = actionCreateStep;
}
void discMotorTunrZero()
{
//rstActtionList();
pAction[actionCreateStep].ActionAxis = DISC_TURNING_AXIS;
pAction[actionCreateStep].status = MOVE_ORG;
pAction[actionCreateStep].ControlMode = Liner_Pos_Zero_Return;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
//motorAction.Step = actionCreateStep;
}
void rstActtionList()
{
memset(&motorAction,0,sizeof(Motor_Action_t));
pAction = &motorAction.Action[0];
actionCreateStep = 0;
}
void discMotorMovePluse(int32_t pluse)
{
pAction[actionCreateStep].ActionAxis = DISC_TURNING_AXIS;
pAction[actionCreateStep].status = MOVE_PLUSE;
pAction[actionCreateStep].Postiontion = abs(pluse);
if (pluse>=0)
pAction[actionCreateStep].ControlMode = Liner_Nes_Pre_NoOrgSL;
else
pAction[actionCreateStep].ControlMode = Liner_Pos_Pre_NoOrgSL;
pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void startCentrifugeTubeCapMotor()
{
SETSTART();
osDelay(1);
CLRSTART();
osDelay(1);
SETSTART();
}
void changeStatus(int8_t hole,int8_t doorHole,int8_t devStatus)
{
pAction[actionCreateStep].ActionAxis = 0;
pAction[actionCreateStep].status = CHANGESTATUS;
pAction[actionCreateStep].hole = hole;
pAction[actionCreateStep].doorhole = doorHole;
pAction[actionCreateStep].devStatus = devStatus;
//pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
void SaveCapStatus(int8_t hole,int8_t doorHole)
{
pAction[actionCreateStep].ActionAxis = 0;
pAction[actionCreateStep].status = WRITECAPSTATUS;
pAction[actionCreateStep].hole = hole;
pAction[actionCreateStep].doorhole = doorHole;
//pAction[actionCreateStep].devStatus = devStatus;
//pAction[actionCreateStep].StartMode= Start_Motor_IntDisable_HighSpeed;
actionCreateStep++;
}
BaseAction.h
#ifndef __BASEACTION_H
#define __BASEACTION_H
#include "cmsis_os2.h"
#include "sys_stru.h"
extern void releaseCentrifugeTubeClamp(void);
extern void z_CentrifugeTubeMotorTurnZero(void);
extern void z_CentrifugeTubeMotorMovePluse(int32_t pluse);
extern void unFixCentrifugeMovePlus(void);
extern void z_CentrifugeTubeMotorMovePosition(int32_t position);
extern void fixCentrifugeMotorMovePlus(int32_t pluse);
extern void fixCentrifugeMotorMovePosition(int32_t position);
extern void unFixCentrifuge(void);
extern void centrifugeTubeClampMotorMovePosition(int32_t position);
extern void unFixPcrTube(void);
extern void z_PcrTubeMotorTurnZero(void);
extern void z_PcrTubeMotorMovePosition(int32_t position);
extern void fixPcrTubeMotorMovePosition(int32_t position);
extern void pcrTubeClampMotorMovePosition(int32_t position);
extern void pcrTubeClampMotorMovePlus(int32_t position);
extern void releasePcrTubeClamp(void);
extern void tied_CentrifugeTubeCap(void);
extern void loose_CentrifugeTubeCap(void);
extern void createMoveAxisTestModeAction(uint8_t axis,uint32_t position);
extern void rstActtionList(void);
extern void discMotorTunrZero(void);
extern void discMotorMovePluse(int32_t pluse);
extern void disRotation(int32_t angle);
extern void startCentrifugeTubeCapMotor(void);
extern void changeStatus(int8_t hole,int8_t doorHole,int8_t devStatus);
extern void SaveCapStatus(int8_t hole,int8_t doorHole);
#endif
CentrifugeTubeAction.c
#include "cmsis_os2.h"
#include "pcd4641.h"
#include "string.h"
#include "MotorControl.h"
#include "BaseAction.h"
void createTiedCentrifugeAction(uint8_t well,uint8_t nextWell)
{
motor_Para_t *axisP;
uint16_t roateAngle;
uint8_t hole;
rstActtionList();
//changeStatus(0,0,0x43);
axisP = &saveMotorPara.DetalPara.para[0];
// TODO 圆盘旋转到紧盖位置
if (well<=Max_Hole && well !=Omit_Well)
disRotation(saveDiscAnglePara.AnglePara.centrifugeTubeAngle[well-1]);
// 固定离心管
fixCentrifugeMotorMovePosition((int32_t)axisP[FIXED_CENTRIFUGE_AXIS].MoveDistace);
// Z 轴运动到位
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
// 拧盖
tied_CentrifugeTubeCap();
// 夹爪张开
SaveCapStatus(0,0);
releaseCentrifugeTubeClamp();
// Z归零 此时夹爪张开状态
//z_CentrifugeTubeMotorTurnZero();
z_CentrifugeTubeMotorMovePosition(0);
// 松开离心管
unFixCentrifuge();
if (nextWell!=Omit_Well)
nextWell = nextWell/2+1;
if (nextWell<=Max_Hole && nextWell !=Omit_Well)
{
disRotation(saveDiscAnglePara.AnglePara.centrifugeTubeAngle[nextWell-1]);
// 固定离心管
fixCentrifugeMotorMovePosition((int32_t)axisP[FIXED_CENTRIFUGE_AXIS].MoveDistace);
// z轴运动到位
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
// 夹离心管
SaveCapStatus((nextWell-1)*2+1,0);
centrifugeTubeClampMotorMovePosition((int32_t)axisP[CLAMP_CENTRIFUGE_AXIS].MoveDistace);
// 松盖
loose_CentrifugeTubeCap();
// Z 归零 此时 夹爪有管盖
z_CentrifugeTubeMotorMovePosition(0);
// 松开离心管
SaveCapStatus((nextWell-1)*2+1,(nextWell-1)*2+1);
unFixCentrifuge();
// TODO 圆盘旋转到加液位置
roateAngle = (nextWell-1)*450 + saveDiscAnglePara.AnglePara.discCentrifugeAngle;
roateAngle %=3600;
disRotation(roateAngle);
hole = (nextWell-1)*2+1;
changeStatus(hole,hole,0x20);
}
else
{
roateAngle = (well-1)*450 + saveDiscAnglePara.AnglePara.discCentrifugeAngle;
roateAngle %=3600;
disRotation(roateAngle);
hole = (well-1)*2+1;
changeStatus(0,hole,0x10);
}
motorAction.Step = actionCreateStep;
}
void createLoosedCentrifugeAction(uint8_t well,uint8_t stopWell)
{
motor_Para_t *axisP;
uint8_t hole;
uint16_t roateAngle;
rstActtionList();
axisP = &saveMotorPara.DetalPara.para[0];
//changeStatus(0,0,0x42);
if (well<=Max_Hole && well !=Omit_Well)
disRotation(saveDiscAnglePara.AnglePara.centrifugeTubeAngle[well-1]);
// 固定离心管
fixCentrifugeMotorMovePosition((int32_t)axisP[FIXED_CENTRIFUGE_AXIS].MoveDistace);
// z轴运动到位
z_CentrifugeTubeMotorMovePosition((int32_t)axisP[CENTRIFUGE_Z_AXIS].MoveDistace);
// 夹离心管
SaveCapStatus((well-1)*2+1,0);
centrifugeTubeClampMotorMovePosition((int32_t)axisP[CLAMP_CENTRIFUGE_AXIS].MoveDistace);
// 松盖
loose_CentrifugeTubeCap();
// Z 归零 此时 夹爪有管盖
z_CentrifugeTubeMotorMovePosition(0);
// 松开离心管
SaveCapStatus((well-1)*2+1,(well-1)*2+1);
unFixCentrifuge();
// TODO 圆盘旋转到加液位置
roateAngle = (well-1)*450+ saveDiscAnglePara.AnglePara.discCentrifugeAngle;
roateAngle %=3600;
disRotation(roateAngle);
hole = (well-1)*2+1;
changeStatus(hole,hole,0x20);
motorAction.Step = actionCreateStep;
}
CentrifugeTubeAction.c
#ifndef __CENTRIFUGETUBEACTION_H
#define __CENTRIFUGETUBEACTION_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "cmsis_os2.h"
extern void createTiedCentrifugeAction(uint8_t well,uint8_t StopWell);
extern void createLoosedCentrifugeAction(uint8_t well,uint8_t stopWell);
#ifdef __cplusplus
}
#endif
#endif
pcrTubeAction.c
#include "cmsis_os2.h"
#include "pcd4641.h"
#include "string.h"
#include "MotorControl.h"
#include "BaseAction.h"
void createClosedPcrTubeAction(uint8_t well,uint8_t nextWell)
{
motor_Para_t *axisP;
uint16_t roateAngle;
uint8_t hole;
rstActtionList();
//changeStatus(0,0,0x43);
axisP = &saveMotorPara.DetalPara.para[0];
// TODO 圆盘旋转到紧盖位置
if (well<=Max_Hole && well !=Omit_Well)
disRotation(saveDiscAnglePara.AnglePara.pcrTubeAngle[well-1]);
// 固定Pcr管
fixPcrTubeMotorMovePosition((int32_t)axisP[FIXED_PCRTUBE_AXIS].MoveDistace);
// Z 轴运动到位
z_PcrTubeMotorMovePosition((int32_t)axisP[PCR_Z_AXIS].MoveDistace);
// 夹爪张开
releasePcrTubeClamp();
SaveCapStatus(0,0);
// Z pcr归零
z_PcrTubeMotorTurnZero();
// 释放Pcr管
unFixPcrTube();
nextWell /=2;
if (nextWell<=Max_Hole && nextWell !=Omit_Well)
{
disRotation(saveDiscAnglePara.AnglePara.pcrTubeAngle[nextWell-1]);
// 固定Pcr管
fixPcrTubeMotorMovePosition((int32_t)axisP[FIXED_PCRTUBE_AXIS].MoveDistace);
// z轴运动到位
z_PcrTubeMotorMovePosition((int32_t)axisP[PCR_Z_AXIS].MoveDistace);
// 夹爪抓紧
SaveCapStatus(nextWell*2,0);
pcrTubeClampMotorMovePosition((int32_t)axisP[CLAMP_PCRTUBE_AXIS].MoveDistace);
// Z pcr归零
z_PcrTubeMotorTurnZero();
// 释放离心管
SaveCapStatus(nextWell*2,nextWell*2);
unFixPcrTube();
// TODO 圆盘旋转到加液位置
roateAngle = (nextWell-1)*450 + saveDiscAnglePara.AnglePara.discPcrAngle;
roateAngle %=3600;
disRotation(roateAngle);
hole =(nextWell*2);
changeStatus(hole,hole,0x20);
}
else
{
roateAngle = (well-1)*450 + saveDiscAnglePara.AnglePara.discPcrAngle;
roateAngle %=3600;
disRotation(roateAngle);
hole = well *2;
changeStatus(0,hole,0x10);
}
motorAction.Step = actionCreateStep;
}
void createOpendPcrTubeAction(uint8_t well,uint8_t stopWell)
{
motor_Para_t *axisP;
uint8_t hole;
uint16_t roateAngle;
rstActtionList();
//changeStatus(0,0,0x42);
axisP = &saveMotorPara.DetalPara.para[0];
if (well<=Max_Hole && well !=Omit_Well)
disRotation(saveDiscAnglePara.AnglePara.pcrTubeAngle[well-1]);
// 固定Pcr管
fixPcrTubeMotorMovePosition((int32_t)axisP[FIXED_PCRTUBE_AXIS].MoveDistace);
// z轴运动到位
z_PcrTubeMotorMovePosition((int32_t)axisP[PCR_Z_AXIS].MoveDistace);
// 夹爪抓紧
SaveCapStatus(well*2,0);
pcrTubeClampMotorMovePosition((int32_t)axisP[CLAMP_PCRTUBE_AXIS].MoveDistace);
// Z pcr归零
z_PcrTubeMotorTurnZero();
// 释放离心管
SaveCapStatus(well*2,well*2);
unFixPcrTube();
// TODO 圆盘旋转到加液位置
roateAngle = (well-1)*450 + saveDiscAnglePara.AnglePara.discPcrAngle;
//roateAngle = roateAngle - 900 -saveDiscAnglePara.AnglePara.centrifugeTubeAngle[0] - saveDiscAnglePara.AnglePara.pcrTubeAngle[0];
roateAngle %=3600;
disRotation(roateAngle);
hole = well*2;
changeStatus(hole,hole,0x20);
motorAction.Step = actionCreateStep;
}
pcrTubeActoin.h
#ifndef __PCRTUBEACTION_H
#define __PCRTUBEACTION_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "cmsis_os2.h"
extern void createClosedPcrTubeAction(uint8_t well,uint8_t stopWell);
extern void createOpendPcrTubeAction(uint8_t well,uint8_t stopWell);
#ifdef __cplusplus
}
#endif
#endif
disMotorAction.c
#include "cmsis_os2.h"
#include "pcd4641.h"
#include "string.h"
#include "MotorControl.h"
#include "BaseAction.h"
#include "AppMain.h"
extern DevStatus_t devStatus;
void rstDiscMotorAction()
{
//motor_Para_t *axisP;
uint32_t axis_Status;
rstActtionList();
axis_Status = axis_read_outstatus(DISC_TURNING_AXIS);
if (axis_Status & SORG)
{
discMotorMovePluse(15200);
}
discMotorTunrZero();
discMotorMovePluse(15200);
discMotorTunrZero();
motorAction.Step = actionCreateStep;
}
void discMotorMove(uint8_t well)
{
uint8_t hole;
uint16_t roateAngle;
rstActtionList();
//changeStatus(0,0,0x44);
SaveCapStatus(devStatus.openLidstatus.hole,well);
if (well == 0)
{
disRotation(0);
}
else
{
if (well%2 == 0)
{
hole = well/2;
roateAngle = (hole-1)*450 +saveDiscAnglePara.AnglePara.discPcrAngle;
roateAngle %=3600;
disRotation(roateAngle);
}
else
{
hole = (well-1)/2+1;
roateAngle = (hole-1)*450 +saveDiscAnglePara.AnglePara.discCentrifugeAngle;
//roateAngle = roateAngle - saveDiscAnglePara.AnglePara.centrifugeTubeAngle[0] - saveDiscAnglePara.AnglePara.pcrTubeAngle[0];
roateAngle %=3600;
disRotation(roateAngle);
}
}
changeStatus(devStatus.openLidstatus.hole,well,0x10);
motorAction.Step = actionCreateStep;
}
Delay.c
#include "Delay.h"
#include "os_tick.h"
void Delay_Us(uint32_t u32Us)
{
uint32_t u32Last = SysTick->VAL;
uint32_t u32Cnt = 0;
uint32_t u32Period = OS_Tick_GetInterval();
u32Us *= (SystemCoreClock / 1000000);
while(1)
{
uint32_t u32Now = SysTick->VAL;
if(u32Now != u32Last)
{
if(u32Now < u32Last)
u32Cnt += (u32Last - u32Now);//SYSTICK是递减的计数器就可以.
else
u32Cnt += (u32Period - u32Now + u32Last);
if(u32Cnt >= u32Us)
break; //时间超过/等于要延迟的时间,则退出.
u32Last = u32Now;
}
}
}
Delay.h
#ifndef __SW_DELAY_H__
#define __SW_DELAY_H__
#include "stm32f4xx.h"
#include "cmsis_os2.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void Delay_Us(uint32_t u32Us);
#define delay_us(us) Delay_Us(us)
#define delay_ms(us) Delay_Us(us*1000)
#ifdef __cplusplus
}
#endif
#endif
pcd4641.c
/****************************************************************************
File name: motor.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
电机控制芯片PCD4641
****************************************************************************/
#include "pcd4641.h"
#include "spi.h"
#include "delay.h"
#include "usart.h"
#include "Gpio.h"
#include "stm32f4xx_hal_gpio.h"
#include <stdarg.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
static p_pcd4641_dev_t p_pcd4641_dev;
uint8_t outPutMode[Max_Axis]; // 输出参数 写入OutPut mode 寄存器 0x11--------
void axis_SearchOrg(uint8_t axis_n,uint8_t dir);
void axis_Move(uint8_t axis_n,Motor_ActionInfo_t *pAction);
uint32_t axis_read_rsts(uint8_t axis_n);
void pcd4641_write_command_regs(uint8_t axis_n,uint8_t commd,uint8_t *regs,uint8_t reg_count);
uint32_t axis_read_outstatus(uint8_t axis_n);
void axis_pulse_count_rst(uint8_t axis_n);
const uint16_t distancePercycle[Max_Axis] = {100,100,100,100,100,254,254,100};
const uint16_t MoveLogic[Max_Axis] = {POSTIVE_LOGIC,NEGTIVE_LOGIC,NEGTIVE_LOGIC,NEGTIVE_LOGIC,POSTIVE_LOGIC,NEGTIVE_LOGIC,NEGTIVE_LOGIC,NEGTIVE_LOGIC};
static void pcd4641_gpio_init(void)
{
/*GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOE_CLK_ENABLE(); //开启GPIOB时钟
__HAL_RCC_GPIOG_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_4;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_6;
GPIO_Initure.Mode=GPIO_MODE_INPUT;
GPIO_Initure.Pull=GPIO_PULLUP;
HAL_GPIO_Init(GPIOG,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_3;
GPIO_Initure.Mode=GPIO_MODE_IT_FALLING; //下降沿触发
GPIO_Initure.Pull=GPIO_PULLUP;
HAL_GPIO_Init(GPIOE,&GPIO_Initure);
HAL_NVIC_SetPriority(EXTI3_IRQn,2,0); //抢占优先级为2,子优先级为0
HAL_NVIC_EnableIRQ(EXTI3_IRQn); //使能中断线0
SPI4_Init();*/
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: pcd4641_read_command(uint8_t axis_n,uint8_t commd,uint8_t *rev_regs)
* 功能: 读寄存器 3Byte
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
uint8_t commd, 命令
uint8_t *regs, 数据地址
* 出口参数:无
****************************************************************************/
void pcd4641_read_command(uint8_t axis_n,uint8_t commd,uint8_t *rev_regs)
{
uint8_t i=0;
static axis_sel_code_t axis_sel_code;
memset((void *)&axis_sel_code,0,sizeof(axis_sel_code_t));
axis_sel_code.area.axis = 1<<(axis_n%4);
axis_sel_code.area.type = General_Purpose_Read;
axis_sel_code.area.devcie = axis_n/4;
PCD4641_CS_LOW();
delay_us(100);
SPI4_ReadWriteByte(axis_sel_code.code);
delay_us(5);
SPI4_ReadWriteByte(commd);
for(i=0;i<3;i++)
{
delay_us(5);
rev_regs[i] = SPI4_ReadWriteByte(0xff);
}
PCD4641_CS_HIGH();
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: void pcd4641_write_command_regs(uint8_t axis_n,uint8_t commd,uint8_t *regs,uint8_t reg_count)
* 功能: 写寄存器
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
uint8_t commd, 命令
uint8_t *regs, 数据地址
uint8_t reg_count 数据个数
* 出口参数:无
****************************************************************************/
void pcd4641_write_command_regs(uint8_t axis_n,uint8_t commd,uint8_t *regs,uint8_t reg_count)
{
int i=0;
axis_sel_code_t axis_sel_code;
axis_sel_code.area.axis = 1<<(axis_n%4);
axis_sel_code.area.type = General_Purpose_Write;
axis_sel_code.area.devcie = axis_n/4;
PCD4641_CS_LOW();
delay_us(100);
SPI4_ReadWriteByte(axis_sel_code.code);
delay_us(5);
SPI4_ReadWriteByte(commd);
for(i=0;i<reg_count;i++)
{
delay_us(5);
SPI4_ReadWriteByte(regs[i]);
}
PCD4641_CS_HIGH();
}
//读取芯片信息,测试
void pcd4641_read_info(uint8_t axis_n,uint8_t *regs)
{
pcd4641_read_command(axis_n,EvenData,regs);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_initiate(uint8_t axis_n)
* 功能: 电机轴控制参数初始化,设定OutputMode 倍率 速度 加速度
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:无
****************************************************************************/
void axis_initiate(uint8_t axis_n)
{
unsigned int Access_Time;
unsigned int Ramp_Down_Buf;
unsigned int Hight_Speed,Low_Speed;
unsigned int speed_cal_buf;
unsigned int access_cal_buf;
p_control_para_t p_control_para = &(p_pcd4641_dev->control_para[axis_n]);
uint8_t regs[3];
if (!p_control_para->Roate_logic)
{
pcd4641_write_command_regs(axis_n,NegLoc_ExtendMon,NULL,0); // 写OutPutMode 模式寄存器
}
else
{
pcd4641_write_command_regs(axis_n,PosLoc_ExtendMon,NULL,0); // 写OutPutMode 模式寄存器
}
pcd4641_write_command_regs(axis_n,EvenData,p_control_para->Renv.regs,3); // 设置运行环境参数
if (p_control_para->Mul>0)
{
p_control_para->MulReg= Motor_clk/8192/p_control_para->Mul;
}
else
{
p_control_para->Mul=BaseMul;
p_control_para->MulReg= Motor_clk/8192/p_control_para->Mul;
}
regs[0] = (p_control_para->MulReg)%256;
regs[1] = (p_control_para->MulReg)/256;
pcd4641_write_command_regs(axis_n,Manager_Reg,regs,2);
Hight_Speed = p_control_para->HightSpeed;
Low_Speed = p_control_para->LowSpeed;
speed_cal_buf = Low_Speed*p_control_para->PluseNumPerCycle/MotorBaseCalSpeed;
p_control_para->LowSpeedReg = speed_cal_buf/(p_control_para->Mul);
regs[0] = (p_control_para->LowSpeedReg)%256;
regs[1] = (p_control_para->LowSpeedReg)/256;
pcd4641_write_command_regs(axis_n,Low_Speed_Reg,regs,2);
speed_cal_buf = Hight_Speed*p_control_para->PluseNumPerCycle/MotorBaseCalSpeed;
p_control_para->HighSpeedReg = speed_cal_buf/(p_control_para->Mul);
regs[0] = (p_control_para->HighSpeedReg)%256;
regs[1] = (p_control_para->HighSpeedReg)/256;
pcd4641_write_command_regs(axis_n,High_Speed_Reg,regs,2);
Access_Time = p_control_para->Accesstime;
if (p_control_para->HighSpeedReg!=p_control_para->LowSpeedReg)
access_cal_buf = (Access_Time)*(Motor_clk/1000)/(abs((int)(p_control_para->HighSpeedReg-p_control_para->LowSpeedReg)))/2;
else
access_cal_buf = 0;
p_control_para->Lineeracc = access_cal_buf;
regs[0] = (p_control_para->Lineeracc)%256;
regs[1] = (p_control_para->Lineeracc)/256;
pcd4641_write_command_regs(axis_n,Accel_Reg,regs,2);
Ramp_Down_Buf = abs((int)(p_control_para->HighSpeedReg*p_control_para->HighSpeedReg
-p_control_para->LowSpeedReg*p_control_para->LowSpeedReg));
Ramp_Down_Buf = Ramp_Down_Buf*access_cal_buf;
Ramp_Down_Buf = Ramp_Down_Buf/p_control_para->MulReg/16384;
p_control_para->RampDown = Ramp_Down_Buf;
regs[0] = (p_control_para->RampDown)%256;
regs[1] = (p_control_para->RampDown)/256;
pcd4641_write_command_regs(axis_n,RapmDown_Reg,regs,2);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_SearchOrg(uint8_t axis_n,uint8_t dir)
* 功能: 电机查找原点
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
uint8_t dir 旋转方向
* 出口参数:无
****************************************************************************/
void axis_SearchOrg(uint8_t axis_n,uint8_t dir)
{
if (dir)
pcd4641_write_command_regs(axis_n,Liner_Pos_Zero_Return ,NULL,0);//顺时针查找原点
else
pcd4641_write_command_regs(axis_n,Liner_Nes_Zero_Return,NULL,0);//高速 变速
pcd4641_write_command_regs(axis_n,Start_Motor_IntDisable_HighSpeed,NULL,0);//运行
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_stop(uint8_t axis_n)
* 功能: 电机停止
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:无
****************************************************************************/
void axis_stop(uint8_t axis_n)
{
pcd4641_write_command_regs(axis_n,Stop_Immediate_IntDisable,NULL,0);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_stop_dec(uint8_t axis_n)
* 功能: 电机减速停止
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:无
****************************************************************************/
void axis_stop_dec(uint8_t axis_n)
{
pcd4641_write_command_regs(axis_n,Stop_Deceleration_IntDisable,NULL,0);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_read_msts(uint8_t axis_n)
* 功能: 电机主要状态读取
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:返回状态
bit 0~7:ISTP ISDP ISTA BUSY PLSZ SDP FUP FDWN
BUSY 轴运行
SDP 过加减速点
FUP 加速中
FDWN 减速中
****************************************************************************/
uint8_t axis_read_msts(uint8_t axis_n)
{
uint8_t msts = 0;
axis_sel_code_t axis_sel_code;
axis_sel_code.area.axis = 1<<(axis_n%4);
axis_sel_code.area.type = General_Purpose_Read_Main;
axis_sel_code.area.devcie = axis_n/4;
PCD4641_CS_LOW();
delay_us(100);
SPI4_ReadWriteByte(axis_sel_code.code);
delay_us(5);
msts = SPI4_ReadWriteByte(0xff);
PCD4641_CS_HIGH();
return msts;
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_pulse_count_rst(uint8_t axis_n)
* 功能: 脉冲计数器清零
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:无
****************************************************************************/
void axis_pulse_count_rst(uint8_t axis_n)
{
uint8_t regs[3]={0,0,0};
pcd4641_write_command_regs(axis_n,PulseCount,regs,3);
}
void axis_pulse_count_write(uint8_t axis_n,uint32_t count)
{
uint8_t regs[3]={0,0,0};
regs[0] = (uint8_t)count;
regs[1] = (uint8_t)(count>>8);
regs[2] = (uint8_t)(count>>16);
pcd4641_write_command_regs(axis_n,PulseCount,regs,3);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_rmv_write(uint8_t axis_n,uint32_t count)
* 功能: 电机运行脉冲个数
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:无
****************************************************************************/
void axis_rmv_write(uint8_t axis_n,uint32_t count)
{
uint8_t regs[3]={0,0,0};
regs[0] = (uint8_t)count;
regs[1] = (uint8_t)(count>>8);
regs[2] = (uint8_t)(count>>16);
pcd4641_write_command_regs(axis_n,Counter_Reg,regs,3);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_rmv_write(uint8_t axis_n,uint32_t count)
* 功能: 当前电机位置
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:int32 位置值
****************************************************************************/
int32_t axis_read_pulse_count(uint8_t axis_n)
{
uint8_t rev_regs[3]={0,0,0};
uint32_t count=0;
pcd4641_read_command(axis_n,PulseCount,rev_regs);
count = (((uint32_t)(rev_regs[2]))<<16) + (((uint32_t)(rev_regs[1]))<<8) + rev_regs[0];
if (count>0x7ffff)
count = count - 0x1000000; // 24 bit 补码
return (int32_t)count;
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: uint32_t axis_read_rsts(uint8_t axis_n)
* 功能: 读取外部状态
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:int32 bit[7:0] msts bit[15:8]-rsts[7:0] bit[23:16]-rsts[15:8]
****************************************************************************/
uint32_t axis_read_rsts(uint8_t axis_n)
{
uint8_t rev_regs[3]={0,0,0};
uint32_t sta=0;
pcd4641_read_command(axis_n,RSTS,rev_regs);
sta = (((uint32_t)(rev_regs[2]))<<16) + (((uint32_t)(rev_regs[1]))<<8) + rev_regs[0];
return sta;
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: uint32_t axis_read_rsts(uint8_t axis_n)
* 功能: 读取外部状态
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
* 出口参数:int32 bit[7:0] msts bit[15:8]-rsts[7:0] bit[23:16]-rsts[15:8]
****************************************************************************/
uint32_t axis_read_outstatus(uint8_t axis_n)
{
uint8_t rev_regs[3]={0,0,0};
uint32_t sta=0;
pcd4641_read_command(axis_n,ALL_STATUS,rev_regs);
sta = (((uint32_t)(rev_regs[2]))<<16) + (((uint32_t)(rev_regs[1]))<<8) + rev_regs[0];
return sta;
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_Move(uint8_t axis_n,Motor_ActionInfo_t *pAction)
* 功能: 电机运行
* 调用者:
* 调用
* 入口参数:uint8_t axis_n, 轴
Motor_ActionInfo_t *pAction
* 出口参数:无
****************************************************************************/
void axis_Move(uint8_t axis_n,Motor_ActionInfo_t *pAction)
{
//pcd4641_write_command_regs(1,0x44,NULL,0);
pcd4641_write_command_regs(axis_n,pAction->ControlMode,NULL,0);
pcd4641_write_command_regs(axis_n,pAction->StartMode,NULL,0);
//pcd4641_write_command_regs(1,0X15,NULL,0);
}
/****************************************************************************
File name: pcd4641.C
Author: Wangyong Version: 1.0 Date: 2030-04-14
* 名称: axis_Move(uint8_t axis_n,Motor_ActionInfo_t *pAction)
* 功能: pcd4641 各轴初始化
* 调用者:
* 调用
* 入口参数:p_pcd4641_dev_t pdev, 驱动对象
motor_Save_t *p_Para 初始化参数
* 出口参数:无
****************************************************************************/
uint8_t pcd4641_init(p_pcd4641_dev_t pdev,motor_Save_t *p_Para)
{
renv_t renv_buff;
int8_t i;
motor_Para_t *p;
p_pcd4641_dev = pdev;
for (i=0;i<Max_Axis;i++)
{
p = &p_Para->DetalPara.para[i];
pdev->control_para[i].Mul=20; //放大倍数
pdev->control_para[i].MulReg=0; //放大倍数寄存器
pdev->control_para[i].HighSpeedReg=0; //最大速度寄存器
pdev->control_para[i].LowSpeedReg=0; //最低速度寄存器
pdev->control_para[i].Lineeracc=0; //线性
pdev->control_para[i].RampDown=0; //降速点位置
pdev->control_para[i].Accesstime=200; //加减速时间 ms
pdev->control_para[i].Renv.regs[0]=0x7b;
pdev->control_para[i].Renv.regs[1]=2;
pdev->control_para[i].Renv.regs[2]=0;
pdev->control_para[i].Roate_logic = MoveLogic[i];
pdev->control_para[i].PluseNumPerCycle = 25600;
pdev->control_para[i].DistancePerCycle = distancePercycle[i];
pdev->control_para[i].HightSpeed=p->HighSpeed; //最大转速
pdev->control_para[i].LowSpeed=p->LowSpeed; //最小转速
//pdev->control_para[i].Accesstime=p->AssessTime; //加减速时间 ms
//pcd4641_gpio_init();
axis_initiate(i);
delay_us(500);
}
pcd4641_read_info(4,renv_buff.regs);
return 1;
}
/****************************** 以下接口预留 ******************************/
void axis_set_mul(uint8_t axis_n,uint16_t mul)
{
uint8_t regs[2]={0,0};
uint16_t Mul_Value;
p_control_para_t p_control_para = &(p_pcd4641_dev->control_para[axis_n]);
Mul_Value = mul;
p_control_para->MulReg= Motor_clk/8192/Mul_Value;
p_control_para->Mul = Mul_Value;
regs[0] = (p_control_para->MulReg)/256;
regs[1] = (p_control_para->MulReg)%256;
pcd4641_write_command_regs(axis_n,Manager_Reg,regs,2);
}
void axis_set_speed(uint8_t axis_n,uint32_t hspeed,uint32_t lspeed)
{
uint32_t speed_cal_buf;
uint32_t access_cal_buf;
uint8_t regs[2]={0,0};
p_control_para_t p_control_para = &(p_pcd4641_dev->control_para[axis_n]);
p_control_para->HightSpeed = hspeed;
p_control_para->LowSpeed = lspeed;
speed_cal_buf = lspeed*MotorSpeedBasePulse/MotorBaseCalSpeed;
p_control_para->LowSpeedReg = speed_cal_buf/(p_control_para->Mul);
regs[0] = (p_control_para->LowSpeedReg)/256;
regs[1] = (p_control_para->LowSpeedReg)%256;
pcd4641_write_command_regs(axis_n,Low_Speed_Reg,regs,2);
speed_cal_buf = hspeed*MotorSpeedBasePulse/MotorBaseCalSpeed;
speed_cal_buf /= p_control_para->Mul;
regs[0] = (p_control_para->HighSpeedReg)/256;
regs[1] = (p_control_para->HighSpeedReg)%256;
pcd4641_write_command_regs(axis_n,High_Speed_Reg,regs,2);
}
void axis_set_access(uint8_t axis_n,uint32_t access_time)
{
uint32_t access_cal_buf;
uint8_t regs[2]={0,0};
p_control_para_t p_control_para = &(p_pcd4641_dev->control_para[axis_n]);
p_control_para->Accesstime = access_time;
if (p_control_para->HighSpeedReg!=p_control_para->LowSpeedReg)
access_cal_buf = (access_time)*(Motor_clk/1000)/(abs((int)(p_control_para->HighSpeedReg-p_control_para->LowSpeedReg)))/2;
else
access_cal_buf = 0;
p_control_para->Lineeracc = access_cal_buf;
regs[0] = access_cal_buf/256;
regs[1]= access_cal_buf%256;
pcd4641_write_command_regs(axis_n,Accel_Reg,regs,2);
}
void axis_run(uint8_t axis_n,uint8_t dir,uint32_t loc,uint32_t hspeed,uint32_t lspeed)
{
static uint32_t state = 0;
state = axis_read_msts(axis_n); //读取主状态
state = axis_read_rsts(axis_n); //读取外部状态
axis_rmv_write(axis_n,loc); //运行脉冲数
axis_set_speed(axis_n,hspeed,lspeed); //设置运行速度
if(dir)
{
if(state & (1ul<<2)) //说明在原点
{
pcd4641_write_command_regs(axis_n,Liner_Nes_Pre_NoOrgSL,NULL,0);//往右
}
else
{
pcd4641_write_command_regs(axis_n,Liner_Nes_Pre_OrgSL,NULL,0);//往右
}
//Motor_Control_Ptr->WR_Command =Start_Motor_IntDisable_LowSpeedCon ; //低速 常速
// pcd4641_write_command_regs(AXIS_X,Start_Motor_IntDisable_LowSpeedCon,NULL,0);//低速 常速
pcd4641_write_command_regs(axis_n,Start_Motor_IntDisable_HighSpeed,NULL,0);//高速 变速
}
else
{
pcd4641_write_command_regs(axis_n,Liner_Pos_Pre_OrgSL,NULL,0);//往左
pcd4641_write_command_regs(axis_n,Start_Motor_IntEnable_HighSpeed,NULL,0);//高速 变速
//Motor_Control_Ptr->WR_Command =Start_Motor_IntEnable_LowSpeedCon ;//低速 常速
}
}
void EXTI3_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_3) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);
}
}
pcd4641.h
#ifndef __PCD4641_H
#define __PCD4641_H
#include "cmsis_os2.h"
#include "sys_stru.h"
#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------------------*/
/* Motor Control Start Command */
/*-------------------------------------------------------------------*/
#define Start_Motor_IntEnable_LowSpeedCon 0x30 // 常速驱动 中断开 STOP:以FL启动 RUNING:立即变为FL
#define Start_Motor_IntEnable_HighSpeed 0x35 // 变速驱动 中断开 STOP:以FH启动 RUNING:加速至FH
#define Start_Motor_IntDisable_HighSpeed 0x15 // 变速驱动 中断关 STOP:以FH启动 RUNING:加速至FH
#define Start_Motor_IntDisable_LowSpeed 0x10 // 常速驱动 中断关 STOP:以FL启动 RUNING:立即变为FL
#define Start_Motor_IntDisable_HighSpeedCon 0x11 // 常速驱动 中断关 STOP:以FH启动 RUNING:立即变为FH
#define Stop_Immediate_IntDisable 0x08 // 立即停止 中断关
#define Stop_Immediate_IntEnable 0x28 // 立即停止 中断开
#define Stop_Deceleration_IntDisable 0x1D // 减速停止 中断关
#define Stop_Deceleration_IntEnable 0x3D // 减速停止 中断开
/*-------------------------------------------------------------------*/
/* Motor Control Mode Command */
/*-------------------------------------------------------------------*/
#define Liner_Pos_Zero_Return 0x43 // 线性逆时针驱动,搜寻原点
#define Liner_Nes_Zero_Return 0x4b // 线性顺时针驱动,搜寻原点
#define Scurve_Pos_Zero_Return 0x63 // 余弦逆时针驱动,搜寻原点
#define Scurve_Nes_Zero_Return 0x6b // 余弦顺时针驱动,搜寻原点
#define Liner_Pos_ReturnNoOrg 0x42 // 线性逆时针驱动
#define Liner_Nes_ReturnNoOrg 0x4a // 线性顺时针驱动
#define Scurve_Pos_Return 0x62 // 余弦逆时针驱动
#define Scurve_Nes_Return 0x6a // 余弦顺时针驱动
#define Liner_Pos_Pre_NoOrgSL 0x44 //线性正方向忽略原点减速
#define Liner_Nes_Pre_NoOrgSL 0x4c //线性负方向忽略原点减速
#define Liner_Pos_Pre_OrgSL 0x45 //线性正方向原点减速
#define Liner_Nes_Pre_OrgSL 0x4d //线性负方向原点减速
#define Scurve_Pos_Pre_NoOrgSL 0x64 //曲线S型正方向忽略原点减速
#define Scurve_Nes_Pre_NoOrgSL 0x6c //曲线S型负方向忽略原点减速
#define ORG_Enable 0x01
#define SL_Enable 0x02
#define ORG_Disable 0xfe
#define SL_Disable 0xfd
/*-------------------------------------------------------------------*/
/* Motor Register Selection Command */
/*-------------------------------------------------------------------*/
#define Counter_Reg 0x80
#define Low_Speed_Reg 0x81
#define High_Speed_Reg 0x82
#define Accel_Reg 0x83
#define Manager_Reg 0x84
#define RapmDown_Reg 0x85
#define IdlePulse_Reg 0x86
#define StatusRead 0x87
#define EvenData 0x87
#define PulseCount 0x88
#define RSTS 0x89
#define ALL_STATUS 0x10
/*-------------------------------------------------------------------*/
/* Motor Control output mode Command */
/*-------------------------------------------------------------------*/
#define PosLoc_NormalMon 0xd1 //标准正脉冲输出模式
#define NegLoc_NormalMon 0xd0 //标准负脉冲输出模式
#define PosLoc_ExtendMon 0xf1 //扩展正脉冲输出模式
#define NegLoc_ExtendMon 0xf0 //扩展负脉冲输出模式
/*-------------------------------------------------------------------*/
/* Serial I/F Access type */
/*-------------------------------------------------------------------*/
#define General_Purpose_Write 0x00 //0-24bit
#define General_Purpose_Read 0x01 //24bit
#define General_Purpose_Read_Port 0x02 //8bit
#define General_Purpose_Read_Main 0x03 //8bit
#define BaseMul 50
#define MotorBaseStep 25600
#define MotorSpeedBasePulse MotorBaseStep/BaseMul
#define MotorBaseCalSpeed 60
#define Motor_clk 4096000
typedef union
{
struct
{
uint8_t renv_pmd:1;
uint8_t renv_46md:1;
uint8_t renv_dcsp:1;
uint8_t renv_aspd:1;
uint8_t renv_spds:1;
uint8_t renv_elds:1;
uint8_t renv_ords:1;
uint8_t renv_orrs:1;
uint8_t renv_pstp:1;
uint8_t renv_prev:1;
uint8_t renv_mskn:1;
uint8_t renv_iopm:1;
uint8_t renv_ipm1:1;
uint8_t renv_ipm2:1;
uint8_t renv_ipm3:1;
uint8_t renv_ipm4:1;
uint8_t reserve;
}renv_area;
uint8_t regs[3];
}renv_t,*p_renv_t;
typedef struct
{
unsigned int Mul; //放大倍数
unsigned int MulReg; //放大倍数寄存器
unsigned int HighSpeedReg; // 最大速度寄存器
unsigned int LowSpeedReg; // 最低速度寄存器
unsigned int HightSpeed; // 最大转速
unsigned int LowSpeed; // 最小转速
unsigned int Lineeracc; //线性
unsigned int RampDown; //降速点位置
unsigned int Accesstime; //加减速时间 ms
renv_t Renv; //运行环境配置参数
uint8_t Roate_logic; // 旋转逻辑
uint32_t PluseNumPerCycle; // 细分数
uint16_t DistancePerCycle; // 一圈运动距离
}control_para_t,*p_control_para_t;
typedef union
{
struct
{
uint8_t axis:4;
uint8_t type:2;
uint8_t devcie:2;
}area;
uint8_t code;
}axis_sel_code_t,*p_axis_sel_code_t;
typedef struct
{
control_para_t control_para[Max_Axis];
}pcd4641_dev_t,*p_pcd4641_dev_t;
extern p_pcd4641_dev_t p_pcd4641_dev;
extern uint8_t pcd4641_init(p_pcd4641_dev_t dev,motor_Save_t *p_Para);
extern int32_t axis_read_pulse_count(uint8_t axis_n);
extern void axis_run(uint8_t axis_n,uint8_t dir,uint32_t loc,uint32_t hspeed,uint32_t lspeed);
extern void axis_SearchOrg(uint8_t axis_n,uint8_t dir);
extern void axis_stop(uint8_t axis_n);
extern void axis_stop_dec(uint8_t axis_n);
extern void axis_Move(uint8_t axis_n,Motor_ActionInfo_t *pAction);
extern uint32_t axis_read_rsts(uint8_t axis_n);
extern void axis_rmv_write(uint8_t axis_n,uint32_t count);
extern uint8_t axis_read_msts(uint8_t axis_n);
extern void pcd4641_write_command_regs(uint8_t axis_n,uint8_t commd,uint8_t *regs,uint8_t reg_count);
extern uint32_t axis_read_outstatus(uint8_t axis_n);
extern void axis_pulse_count_rst(uint8_t axis_n);
extern void axis_pulse_count_write(uint8_t axis_n,uint32_t count);
#ifdef __cplusplus
}
#endif
#endif
w25qxx.c
#include "w25qxx.h"
#include "spi.h"
#include "delay.h"
#include "usart.h"
#include "stm32f4xx_hal_gpio.h"
#include "sys.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//W25QXX驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/16
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//
uint16_t W25QXX_TYPE=W25Q16; //默认是W25Q256
uint8_t W25QXX_BUFFER[4096] __attribute__((at(0xc0011200)));
//4Kbytes为一个Sector
//16个扇区为1个Block
//W25Q256
//容量为32M字节,共有512个Block,8192个Sector
//初始化SPI FLASH的IO口
void W25QXX_Init(void)
{
uint8_t temp;
//__HAL_RCC_GPIOF_CLK_ENABLE(); //使能GPIOF时钟
//PF6
/*GPIO_Initure.Pin=GPIO_PIN_6; //PF6
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //快速
HAL_GPIO_Init(GPIOF,&GPIO_Initure); //初始化*/
W25QXX_CS=1; //SPI FLASH不选中
//SPI5_Init(); //初始化SPI
SPI5_SetSpeed(SPI_BAUDRATEPRESCALER_2); //设置为45M时钟,高速模式
W25QXX_TYPE=W25QXX_ReadID(); //读取FLASH ID.
if(W25QXX_TYPE==W25Q256) //SPI FLASH为W25Q256
{
temp=W25QXX_ReadSR(3); //读取状态寄存器3,判断地址模式
if((temp&0X01)==0) //如果不是4字节地址模式,则进入4字节地址模式
{
W25QXX_CS=0; //选中
SPI5_ReadWriteByte(W25X_Enable4ByteAddr);//发送进入4字节地址模式指令
W25QXX_CS=1; //取消片选
}
}
}
//读取W25QXX的状态寄存器,W25QXX一共有3个状态寄存器
//状态寄存器1:
//BIT7 6 5 4 3 2 1 0
//SPR RV TB BP2 BP1 BP0 WEL BUSY
//SPR:默认0,状态寄存器保护位,配合WP使用
//TB,BP2,BP1,BP0:FLASH区域写保护设置
//WEL:写使能锁定
//BUSY:忙标记位(1,忙;0,空闲)
//默认:0x00
//状态寄存器2:
//BIT7 6 5 4 3 2 1 0
//SUS CMP LB3 LB2 LB1 (R) QE SRP1
//状态寄存器3:
//BIT7 6 5 4 3 2 1 0
//HOLD/RST DRV1 DRV0 (R) (R) WPS ADP ADS
//regno:状态寄存器号,范:1~3
//返回值:状态寄存器值
uint8_t W25QXX_ReadSR(uint8_t regno)
{
uint8_t byte=0,command=0;
switch(regno)
{
case 1:
command=W25X_ReadStatusReg1; //读状态寄存器1指令
break;
case 2:
command=W25X_ReadStatusReg2; //读状态寄存器2指令
break;
case 3:
command=W25X_ReadStatusReg3; //读状态寄存器3指令
break;
default:
command=W25X_ReadStatusReg1;
break;
}
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(command); //发送读取状态寄存器命令
byte=SPI5_ReadWriteByte(0Xff); //读取一个字节
W25QXX_CS=1; //取消片选
return byte;
}
//写W25QXX状态寄存器
void W25QXX_Write_SR(uint8_t regno,uint8_t sr)
{
uint8_t command=0;
switch(regno)
{
case 1:
command=W25X_WriteStatusReg1; //写状态寄存器1指令
break;
case 2:
command=W25X_WriteStatusReg2; //写状态寄存器2指令
break;
case 3:
command=W25X_WriteStatusReg3; //写状态寄存器3指令
break;
default:
command=W25X_WriteStatusReg1;
break;
}
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(command); //发送写取状态寄存器命令
SPI5_ReadWriteByte(sr); //写入一个字节
W25QXX_CS=1; //取消片选
}
//W25QXX写使能
//将WEL置位
void W25QXX_Write_Enable(void)
{
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_WriteEnable); //发送写使能
W25QXX_CS=1; //取消片选
}
//W25QXX写禁止
//将WEL清零
void W25QXX_Write_Disable(void)
{
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_WriteDisable); //发送写禁止指令
W25QXX_CS=1; //取消片选
}
//读取芯片ID
//返回值如下:
//0XEF13,表示芯片型号为W25Q80
//0XEF14,表示芯片型号为W25Q16
//0XEF15,表示芯片型号为W25Q32
//0XEF16,表示芯片型号为W25Q64
//0XEF17,表示芯片型号为W25Q128
//0XEF18,表示芯片型号为W25Q256
uint16_t W25QXX_ReadID(void)
{
uint16_t Temp = 0;
W25QXX_CS=0;
SPI5_ReadWriteByte(0x90);//发送读取ID命令
SPI5_ReadWriteByte(0x00);
SPI5_ReadWriteByte(0x00);
SPI5_ReadWriteByte(0x00);
Temp|=SPI5_ReadWriteByte(0xFF)<<8;
Temp|=SPI5_ReadWriteByte(0xFF);
W25QXX_CS=1;
return Temp;
}
//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
uint16_t i;
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_ReadData); //发送读取命令
if(W25QXX_TYPE==W25Q256) //如果是W25Q256的话地址为4字节的,要发送最高8位
{
SPI5_ReadWriteByte((uint8_t)((ReadAddr)>>24));
}
SPI5_ReadWriteByte((uint8_t)((ReadAddr)>>16)); //发送24bit地址
SPI5_ReadWriteByte((uint8_t)((ReadAddr)>>8));
SPI5_ReadWriteByte((uint8_t)ReadAddr);
for(i=0;i<NumByteToRead;i++)
{
pBuffer[i]=SPI5_ReadWriteByte(0XFF); //循环读数
}
W25QXX_CS=1;
}
//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!
void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t i;
W25QXX_Write_Enable(); //SET WEL
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_PageProgram); //发送写页命令
if(W25QXX_TYPE==W25Q256) //如果是W25Q256的话地址为4字节的,要发送最高8位
{
SPI5_ReadWriteByte((uint8_t)((WriteAddr)>>24));
}
SPI5_ReadWriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址
SPI5_ReadWriteByte((uint8_t)((WriteAddr)>>8));
SPI5_ReadWriteByte((uint8_t)WriteAddr);
for(i=0;i<NumByteToWrite;i++)SPI5_ReadWriteByte(pBuffer[i]);//循环写数
W25QXX_CS=1; //取消片选
W25QXX_Wait_Busy(); //等待写入结束
}
//无检验写SPI FLASH
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
//CHECK OK
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t pageremain;
pageremain=256-WriteAddr%256; //单页剩余的字节数
if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
while(1)
{
W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
if(NumByteToWrite==pageremain)break;//写入结束了
else //NumByteToWrite>pageremain
{
pBuffer+=pageremain;
WriteAddr+=pageremain;
NumByteToWrite-=pageremain; //减去已经写入了的字节数
if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
else pageremain=NumByteToWrite; //不够256个字节了
}
};
}
//写SPI FLASH
//在指定地址开始写入指定长度的数据
//该函数带擦除操作!
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大65535)
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t * W25QXX_BUF;
W25QXX_BUF=W25QXX_BUFFER;
secpos=WriteAddr/4096;//扇区地址
secoff=WriteAddr%4096;//在扇区内的偏移
secremain=4096-secoff;//扇区剩余空间大小
//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用
if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
while(1)
{
W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区的内容
for(i=0;i<secremain;i++)//校验数据
{
if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除
}
if(i<secremain)//需要擦除
{
W25QXX_Erase_Sector(secpos);//擦除这个扇区
for(i=0;i<secremain;i++) //复制
{
W25QXX_BUF[i+secoff]=pBuffer[i];
}
W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区
}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.
if(NumByteToWrite==secremain)break;//写入结束了
else//写入未结束
{
secpos++;//扇区地址增1
secoff=0;//偏移位置为0
pBuffer+=secremain; //指针偏移
WriteAddr+=secremain;//写地址偏移
NumByteToWrite-=secremain; //字节数递减
if(NumByteToWrite>4096)secremain=4096; //下一个扇区还是写不完
else secremain=NumByteToWrite; //下一个扇区可以写完了
}
};
}
//擦除整个芯片
//等待时间超长...
void W25QXX_Erase_Chip(void)
{
W25QXX_Write_Enable(); //SET WEL
W25QXX_Wait_Busy();
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_ChipErase); //发送片擦除命令
W25QXX_CS=1; //取消片选
W25QXX_Wait_Busy(); //等待芯片擦除结束
}
//擦除一个扇区
//Dst_Addr:扇区地址 根据实际容量设置
//擦除一个扇区的最少时间:150ms
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{
//监视falsh擦除情况,测试用
//printf("fe:%x\r\n",Dst_Addr);
Dst_Addr*=4096;
W25QXX_Write_Enable(); //SET WEL
W25QXX_Wait_Busy();
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令
if(W25QXX_TYPE==W25Q256) //如果是W25Q256的话地址为4字节的,要发送最高8位
{
SPI5_ReadWriteByte((uint8_t)((Dst_Addr)>>24));
}
SPI5_ReadWriteByte((uint8_t)((Dst_Addr)>>16)); //发送24bit地址
SPI5_ReadWriteByte((uint8_t)((Dst_Addr)>>8));
SPI5_ReadWriteByte((uint8_t)Dst_Addr);
W25QXX_CS=1; //取消片选
W25QXX_Wait_Busy(); //等待擦除完成
}
//等待空闲
void W25QXX_Wait_Busy(void)
{
while((W25QXX_ReadSR(1)&0x01)==0x01); // 等待BUSY位清空
}
//进入掉电模式
void W25QXX_PowerDown(void)
{
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_PowerDown); //发送掉电命令
W25QXX_CS=1; //取消片选
delay_us(3); //等待TPD
}
//唤醒
void W25QXX_WAKEUP(void)
{
W25QXX_CS=0; //使能器件
SPI5_ReadWriteByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB
W25QXX_CS=1; //取消片选
delay_us(3); //等待TRES1
}
w25qxx.h
#ifndef __W25QXX_H
#define __W25QXX_H
#include "cmsis_os2.h"
//#include "sys.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//W25QXX驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/16
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//
//W25X系列/Q系列芯片列表
//W25Q80 ID 0XEF13
//W25Q16 ID 0XEF14
//W25Q32 ID 0XEF15
//W25Q64 ID 0XEF16
//W25Q128 ID 0XEF17
//W25Q256 ID 0XEF18
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17
#define W25Q256 0XEF18
extern uint16_t W25QXX_TYPE; //定义W25QXX芯片型号
#define W25QXX_CS PFout(6) //W25QXX的片选信号
//
//指令表
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg1 0x05
#define W25X_ReadStatusReg2 0x35
#define W25X_ReadStatusReg3 0x15
#define W25X_WriteStatusReg1 0x01
#define W25X_WriteStatusReg2 0x31
#define W25X_WriteStatusReg3 0x11
#define W25X_ReadData 0x03
#define W25X_FastReadData 0x0B
#define W25X_FastReadDual 0x3B
#define W25X_PageProgram 0x02
#define W25X_BlockErase 0xD8
#define W25X_SectorErase 0x20
#define W25X_ChipErase 0xC7
#define W25X_PowerDown 0xB9
#define W25X_ReleasePowerDown 0xAB
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
#define W25X_Enable4ByteAddr 0xB7
#define W25X_Exit4ByteAddr 0xE9
extern void W25QXX_Init(void);
extern uint16_t W25QXX_ReadID(void); //读取FLASH ID
extern uint8_t W25QXX_ReadSR(uint8_t regno); //读取状态寄存器
extern void W25QXX_4ByteAddr_Enable(void); //使能4字节地址模式
extern void W25QXX_Write_SR(uint8_t regno,uint8_t sr); //写状态寄存器
extern void W25QXX_Write_Enable(void); //写使能
extern void W25QXX_Write_Disable(void); //写保护
extern void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
extern void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead); //读取flash
extern void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);//写入flash
extern void W25QXX_Erase_Chip(void); //整片擦除
extern void W25QXX_Erase_Sector(uint32_t Dst_Addr); //扇区擦除
extern void W25QXX_Wait_Busy(void); //等待空闲
extern void W25QXX_PowerDown(void); //进入掉电模式
extern void W25QXX_WAKEUP(void); //唤醒
#endif
RAM_INFO.txt
RAM 说明
内部RAM 0x20000000 size 0x30000
- os 使用 0x20028000 ~ 0x2002ffff 32k 统一设置为 8字节对齐
静态分配 各线程 stack_mem, message data_mem
使用情况
0x20028000 ~ 0x20007ff size 2k 电机控制线程 stack
0x20028800 ~ 0x20009ff size 512 app启动线程 stack
0x20028a00 ~ 0x2000bff size 512 Can发送进程 stack
//0x20007000~0x20077ff size 2k Can Send messageQeue
0x20008000~0x20079ff size 512 Encode SenMessageQeue
以上地址 IAP 根据 iap 调整
- 全局,栈,堆 使用 0x2008000 ~ 0x202ffff 160k
0xc0013200 size 2k Can Send messageQeue
外部SRAM 0xc000000
stm32f4xx_it.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern CAN_HandleTypeDef hcan1;
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */
extern uint8_t ustart3RdChar;
extern uint8_t uart4RdChar;
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* @brief This function handles CAN1 RX0 interrupts.
*/
void CAN1_RX0_IRQHandler(void)
{
/* USER CODE BEGIN CAN1_RX0_IRQn 0 */
/* USER CODE END CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1);
/* USER CODE BEGIN CAN1_RX0_IRQn 1 */
/* USER CODE END CAN1_RX0_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/*if(__HAL_UART_GET_FLAG( &huart3, UART_FLAG_RXNE ) != RESET)
{
HAL_UART_Receive(&huart3, (uint8_t *)&ustart3RdChar, 1, 100);
HAL_UART_Transmit(&huart3, &ustart3RdChar, 1,10);
}*/
//HAL_UART_Transmit(&huart3, &ustart3RdChar, 1,10);
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
HAL_UART_Receive_IT(&huart3, (uint8_t *)&ustart3RdChar, 1);
/* USER CODE END USART3_IRQn 1 */
}
/**
* @brief This function handles UART4 global interrupt.
*/
void UART4_IRQHandler(void)
{
/* USER CODE BEGIN UART4_IRQn 0 */
/* USER CODE END UART4_IRQn 0 */
HAL_UART_IRQHandler(&huart4);
/* USER CODE BEGIN UART4_IRQn 1 */
HAL_UART_Receive_IT(&huart4, (uint8_t *)&uart4RdChar, 1);
/* USER CODE END UART4_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include "fmc.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "RTE_Components.h"
#ifdef RTE_Compiler_EventRecorder
#include "EventRecorder.h"
#endif
#include "cmsis_os2.h"
#include "Appmain.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint32_t HAL_GetTick (void) {
static uint32_t ticks = 0U;
uint32_t i;
if (osKernelGetState () == osKernelRunning) {
return ((uint32_t)osKernelGetTickCount ());
}
/* If Kernel is not running wait approximately 1 ms then increment and return auxiliary tick counter value */
for (i = (SystemCoreClock >> 14U); i > 0U; i--) { __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); }
return ++ticks; }
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_FMC_Init();
MX_CAN1_Init();
MX_SPI4_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
MX_UART4_Init();
MX_SPI5_Init();
/* USER CODE BEGIN 2 */
// 初始化外设 开中断
MX_SDRAM_InitEx();
#ifdef RTE_Compiler_EventRecorder
EventRecorderInitialize(EventRecordAll, 1);
#endif
SystemCoreClockUpdate();
osKernelInitialize(); // Initialize CMSIS-RTOS
//osThreadNew(app_main, NULL, NULL); // Create application main thread
Init_appMainThreadThread();
osKernelStart();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 360;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Activate the Over-Drive mode
*/
if (HAL_PWREx_EnableOverDrive() != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
gpio.c
/**
******************************************************************************
* File Name : gpio.c
* Description : This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
PB5 ------> CAN2_RX
PB6 ------> CAN2_TX
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(SPI_FLASH_CS_GPIO_Port, SPI_FLASH_CS_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, Run_Led_Pin|Status_Led_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = SPI_INT_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SPI_INT_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = SPI_CS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SPI_CS_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = SPI_FLASH_CS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SPI_FLASH_CS_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PAPin PAPin PAPin PAPin */
GPIO_InitStruct.Pin = ID0_Pin|ID1_Pin|ID2_Pin|ID3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PBPin PBPin */
GPIO_InitStruct.Pin = Run_Led_Pin|Status_Led_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : PH6 PH7 PH8 PH9
PH12 PH13 PH14 PH15 */
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/*Configure GPIO pins : PGPin PGPin PGPin PGPin */
GPIO_InitStruct.Pin = W_BUSY_Pin|Z_BUSY_Pin|X_BUSY_Pin|Y_BUSY_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pins : PI0 PI1 PI2 PI3
PI4 PI5 PI6 PI7 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
/*Configure GPIO pins : PB5 PB6 */
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
gpio.h
/**
******************************************************************************
* File Name : gpio.h
* Description : This file contains all the functions prototypes for
* the gpio
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __gpio_H
#define __gpio_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
#define SETH(p,i) p->BSRR=i //输出为高电平
#define CLRL(p,i) p->BSRR=i<<16U //输出低电平
#define digitalToggle(p,i) p->ODR ^=i //输出反转状态
#define INPUT(p,i) (p->IDR & i)
#define PCD4641_CS_HIGH() SETH(SPI_CS_GPIO_Port,SPI_CS_Pin)
#define PCD4641_CS_LOW() CLRL(SPI_CS_GPIO_Port,SPI_CS_Pin)
/*#define BOARD_ID HAL_GPIO_ReadPin(ID3_GPIO_Port,ID3_Pin)<<3 \
+ HAL_GPIO_ReadPin(ID2_GPIO_Port,ID2_Pin)<<2 \
+ HAL_GPIO_ReadPin(ID1_GPIO_Port,ID1_Pin)<<1 \
+ HAL_GPIO_ReadPin(ID0_GPIO_Port,ID0_Pin)*/
#define BOARD_ID (ID3_GPIO_Port->IDR & (ID3_Pin|ID2_Pin|ID1_Pin|ID0_Pin))>>4
#define DEVICE_ID 0x9
#define MOVE (GPIOH->IDR & GPIO_PIN_6)
#define READY (GPIOH->IDR & GPIO_PIN_7)
#define TLC (GPIOH->IDR & GPIO_PIN_6)
#define MOTORALARM (GPIOH->IDR & GPIO_PIN_9)
#define SETSTART() SETH(GPIOI,GPIO_PIN_0)
#define CLRSTART() CLRL(GPIOI,GPIO_PIN_0)
#define CLRALLMODE() CLRL(GPIOI,(GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3))
#define SETALLMODE() SETH(GPIOI,(GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3))
#define SETM0() SETH(GPIOI,GPIO_PIN_1)
#define SETM1() SETH(GPIOI,GPIO_PIN_2)
#define CLRM0() CLRL(GPIOI,GPIO_PIN_1)
/* USER CODE END Private defines */
void MX_GPIO_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ pinoutConfig_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
fmc.c
/**
******************************************************************************
* File Name : FMC.c
* Description : This file provides code for the configuration
* of the FMC peripheral.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "fmc.h"
/* USER CODE BEGIN 0 */
//向SDRAM发送命令
//bankx:0,向BANK5上面的SDRAM发送指令
// 1,向BANK6上面的SDRAM发送指令
//cmd:指令(0,正常模式/1,时钟配置使能/2,预充电所有存储区/3,自动刷新/4,加载模式寄存器/5,自刷新/6,掉电)
//refresh:自刷新次数
//regval:模式寄存器的定义
//返回值:0,正常;1,失败.
uint8_t SDRAM_Send_Cmd(uint8_t bankx,uint8_t cmd,uint8_t refresh,uint16_t regval)
{
uint32_t target_bank=0;
FMC_SDRAM_CommandTypeDef Command;
if(bankx==0) target_bank=FMC_SDRAM_CMD_TARGET_BANK1;
else if(bankx==1) target_bank=FMC_SDRAM_CMD_TARGET_BANK2;
Command.CommandMode=cmd; //命令
Command.CommandTarget=target_bank; //目标SDRAM存储区域
Command.AutoRefreshNumber=refresh; //自刷新次数
Command.ModeRegisterDefinition=regval; //要写入模式寄存器的值
if(HAL_SDRAM_SendCommand(&hsdram1,&Command,0X1000)==HAL_OK) //向SDRAM发送命令
{
return 0;
}
else return 1;
}
//发送SDRAM初始化序列
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
uint32_t temp=0;
//SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAM
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0); //时钟配置使能
HAL_Delay(1); //至少延时200us
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_PALL,1,0); //对所有存储区预充电
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8,0);//设置自刷新次数
//配置模式寄存器,SDRAM的bit0~bit2为指定突发访问的长度,
//bit3为指定突发访问的类型,bit4~bit6为CAS值,bit7和bit8为运行模式
//bit9为指定的写突发模式,bit10和bit11位保留位
temp=(uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | //设置突发长度:1(可以是1/2/4/8)
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | //设置突发类型:连续(可以是连续/交错)
SDRAM_MODEREG_CAS_LATENCY_3 | //设置CAS值:3(可以是2/3)
SDRAM_MODEREG_OPERATING_MODE_STANDARD | //设置操作模式:0,标准模式
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; //设置突发写模式:1,单点访问
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_LOAD_MODE,1,temp); //设置SDRAM的模式寄存器
}
void MX_SDRAM_InitEx(void)
{
SDRAM_Initialization_Sequence(&hsdram1);
//刷新频率计数器(以SDCLK频率计数),计算方法:
//COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
//我们使用的SDRAM刷新周期为64ms,SDCLK=180/2=90Mhz,行数为8192(2^13).
//所以,COUNT=64*1000*90/8192-20=683
HAL_SDRAM_ProgramRefreshRate(&hsdram1,683);//设置刷新频率
}
/* USER CODE END 0 */
SDRAM_HandleTypeDef hsdram1;
/* FMC initialization function */
void MX_FMC_Init(void)
{
FMC_SDRAM_TimingTypeDef SdramTiming = {0};
/** Perform the SDRAM1 memory initialization sequence
*/
hsdram1.Instance = FMC_SDRAM_DEVICE;
/* hsdram1.Init */
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
/* SdramTiming */
SdramTiming.LoadToActiveDelay = 2;
SdramTiming.ExitSelfRefreshDelay = 8;
SdramTiming.SelfRefreshTime = 6;
SdramTiming.RowCycleDelay = 6;
SdramTiming.WriteRecoveryTime = 2;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 6;
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
{
Error_Handler( );
}
}
static uint32_t FMC_Initialized = 0;
static void HAL_FMC_MspInit(void){
/* USER CODE BEGIN FMC_MspInit 0 */
/* USER CODE END FMC_MspInit 0 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (FMC_Initialized) {
return;
}
FMC_Initialized = 1;
/* Peripheral clock enable */
__HAL_RCC_FMC_CLK_ENABLE();
/** FMC GPIO Configuration
PF0 ------> FMC_A0
PF1 ------> FMC_A1
PF2 ------> FMC_A2
PF3 ------> FMC_A3
PF4 ------> FMC_A4
PF5 ------> FMC_A5
PC0 ------> FMC_SDNWE
PC2 ------> FMC_SDNE0
PC3 ------> FMC_SDCKE0
PF11 ------> FMC_SDNRAS
PF12 ------> FMC_A6
PF13 ------> FMC_A7
PF14 ------> FMC_A8
PF15 ------> FMC_A9
PG0 ------> FMC_A10
PG1 ------> FMC_A11
PE7 ------> FMC_D4
PE8 ------> FMC_D5
PE9 ------> FMC_D6
PE10 ------> FMC_D7
PE11 ------> FMC_D8
PE12 ------> FMC_D9
PE13 ------> FMC_D10
PE14 ------> FMC_D11
PE15 ------> FMC_D12
PD8 ------> FMC_D13
PD9 ------> FMC_D14
PD10 ------> FMC_D15
PD14 ------> FMC_D0
PD15 ------> FMC_D1
PG2 ------> FMC_A12
PG4 ------> FMC_BA0
PG5 ------> FMC_BA1
PG8 ------> FMC_SDCLK
PD0 ------> FMC_D2
PD1 ------> FMC_D3
PG15 ------> FMC_SDNCAS
PE0 ------> FMC_NBL0
PE1 ------> FMC_NBL1
*/
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = A0_Pin|A1_Pin|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12
|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4
|GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USER CODE BEGIN FMC_MspInit 1 */
/* USER CODE END FMC_MspInit 1 */
}
void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* sdramHandle){
/* USER CODE BEGIN SDRAM_MspInit 0 */
/* USER CODE END SDRAM_MspInit 0 */
HAL_FMC_MspInit();
/* USER CODE BEGIN SDRAM_MspInit 1 */
/* USER CODE END SDRAM_MspInit 1 */
}
static uint32_t FMC_DeInitialized = 0;
static void HAL_FMC_MspDeInit(void){
/* USER CODE BEGIN FMC_MspDeInit 0 */
/* USER CODE END FMC_MspDeInit 0 */
if (FMC_DeInitialized) {
return;
}
FMC_DeInitialized = 1;
/* Peripheral clock enable */
__HAL_RCC_FMC_CLK_DISABLE();
/** FMC GPIO Configuration
PF0 ------> FMC_A0
PF1 ------> FMC_A1
PF2 ------> FMC_A2
PF3 ------> FMC_A3
PF4 ------> FMC_A4
PF5 ------> FMC_A5
PC0 ------> FMC_SDNWE
PC2 ------> FMC_SDNE0
PC3 ------> FMC_SDCKE0
PF11 ------> FMC_SDNRAS
PF12 ------> FMC_A6
PF13 ------> FMC_A7
PF14 ------> FMC_A8
PF15 ------> FMC_A9
PG0 ------> FMC_A10
PG1 ------> FMC_A11
PE7 ------> FMC_D4
PE8 ------> FMC_D5
PE9 ------> FMC_D6
PE10 ------> FMC_D7
PE11 ------> FMC_D8
PE12 ------> FMC_D9
PE13 ------> FMC_D10
PE14 ------> FMC_D11
PE15 ------> FMC_D12
PD8 ------> FMC_D13
PD9 ------> FMC_D14
PD10 ------> FMC_D15
PD14 ------> FMC_D0
PD15 ------> FMC_D1
PG2 ------> FMC_A12
PG4 ------> FMC_BA0
PG5 ------> FMC_BA1
PG8 ------> FMC_SDCLK
PD0 ------> FMC_D2
PD1 ------> FMC_D3
PG15 ------> FMC_SDNCAS
PE0 ------> FMC_NBL0
PE1 ------> FMC_NBL1
*/
HAL_GPIO_DeInit(GPIOF, A0_Pin|A1_Pin|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12
|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_3);
HAL_GPIO_DeInit(GPIOG, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4
|GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15);
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1);
/* USER CODE BEGIN FMC_MspDeInit 1 */
/* USER CODE END FMC_MspDeInit 1 */
}
void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* sdramHandle){
/* USER CODE BEGIN SDRAM_MspDeInit 0 */
/* USER CODE END SDRAM_MspDeInit 0 */
HAL_FMC_MspDeInit();
/* USER CODE BEGIN SDRAM_MspDeInit 1 */
/* USER CODE END SDRAM_MspDeInit 1 */
}
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
fmc.h
/**
******************************************************************************
* File Name : FMC.h
* Description : This file provides code for the configuration
* of the FMC peripheral.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FMC_H
#define __FMC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
//SDRAM配置参数
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
/* USER CODE END Includes */
extern SDRAM_HandleTypeDef hsdram1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_FMC_Init(void);
void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram);
void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* hsdram);
/* USER CODE BEGIN Prototypes */
void MX_SDRAM_InitEx(void);
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__FMC_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
``
usart.c
```c
/**
******************************************************************************
* File Name : USART.c
* Description : This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
#include "Appmain.h"
uartPack uart3_RcvData __attribute__((at(0xc0000900))); // 接受数据缓冲区
uartPack uart3_MsgRcvBuf[uartMsgBufLength] __attribute__((at(0xc0001200))); // usart3 消息缓冲区
uint8_t ustart3RdChar;
uint16_t uart3_Rd_Point=0;
uint8_t uart3_RcvHead = 0;
uint16_t count=0;
uint8_t uart3_BufWr =0;
uint8_t uart4RdChar;
Message_t uart4RcvMsg;
uint8_t uart4_Rd_point = 0;
// 串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* uartHandle)
{
if (uartHandle->Instance == USART3)
{
count++;
if (ustart3RdChar == '{')
{
uart3_Rd_Point = 1;
uart3_RcvHead = 0;
//uart3_RcvData.packdata[0] = ustart3RdChar;
}
else if (ustart3RdChar == '|' && uart3_RcvHead ==0)
{
uart3_Rd_Point=2;
//uart3_RcvData[1] = ustart3RdChar;
uart3_RcvHead = 1;
}
else
{
if (uart3_RcvHead)
{
if (uart3_Rd_Point<(uartBufLength-2))
{
uart3_RcvData.packdata[uart3_Rd_Point-2] = ustart3RdChar;
if (ustart3RdChar == '}')
{
if (uart3_RcvData.packdata[uart3_Rd_Point-3] == '|')
{
uart3_RcvData.dataLength = uart3_Rd_Point;
uart3_MsgRcvBuf[uart3_BufWr] = uart3_RcvData;
uart3_BufWr++;
uart3_BufWr%=uartMsgBufLength;
osSemaphoreRelease(uart3RcvID);
}
else
{
uart3_Rd_Point = 0;
uart3_RcvHead = 0;
}
}
else
{
uart3_Rd_Point++;
}
}
else
{
uart3_Rd_Point = 0;
uart3_RcvHead = 0;
}
}
}
}
else if (uartHandle->Instance == UART4)
{
uart4RcvMsg.buf[uart4_Rd_point] = uart4RdChar;
uart4_Rd_point++;
if (uart4_Rd_point>sizeof(uart4RcvMsg.buf)-1)
{
uart4_Rd_point = 0;
}
if (uart4RdChar == 0x0d)
{
uart4RcvMsg.Length = uart4_Rd_point-1;
osMessageQueuePut(encodeQSendMsgQ,&uart4RcvMsg,0u,0u);
uart4_Rd_point = 0;
}
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *uartHandle)
{
if (uartHandle->Instance == USART3)
{
uint32_t isrflags = READ_REG(uartHandle->Instance->SR);//清错误都要先读SR
if((__HAL_UART_GET_FLAG(uartHandle, UART_FLAG_PE))!=RESET)
{
READ_REG(uartHandle->Instance->DR);//PE清标志
__HAL_UART_CLEAR_FLAG(uartHandle, UART_FLAG_PE);//清标志
}
if((__HAL_UART_GET_FLAG(uartHandle, UART_FLAG_FE))!=RESET)
{
READ_REG(uartHandle->Instance->DR);
__HAL_UART_CLEAR_FLAG(uartHandle, UART_FLAG_FE);
}
if((__HAL_UART_GET_FLAG(uartHandle, UART_FLAG_NE))!=RESET)
{
READ_REG(uartHandle->Instance->DR);//NE清标志,第二步读DR
__HAL_UART_CLEAR_FLAG(uartHandle, UART_FLAG_NE);
}
if((__HAL_UART_GET_FLAG(uartHandle, UART_FLAG_ORE))!=RESET)
{
READ_REG(uartHandle->Instance->CR1);//ORE清标志,第二步读CR
__HAL_UART_CLEAR_FLAG(uartHandle, UART_FLAG_ORE);
}
uartHandle->RxState = HAL_UART_STATE_READY;
uart3_Rd_Point = 0;
uart3_RcvHead = 0;
}
else
{
}
}
/* USER CODE END 0 */
UART_HandleTypeDef huart4;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart3;
/* UART4 init function */
void MX_UART4_Init(void)
{
huart4.Instance = UART4;
huart4.Init.BaudRate = 19200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
Error_Handler();
}
}
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/* USART3 init function */
void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = 38400;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspInit 0 */
/* USER CODE END UART4_MspInit 0 */
/* UART4 clock enable */
__HAL_RCC_UART4_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**UART4 GPIO Configuration
PA0/WKUP ------> UART4_TX
PA1 ------> UART4_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspInit 1 */
/* USER CODE END UART4_MspInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
//__HAL_UART_ENABLE_IT(uartHandle,UART_IT_RXNE);
/* USER CODE END USART3_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspDeInit 0 */
/* USER CODE END UART4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART4_CLK_DISABLE();
/**UART4 GPIO Configuration
PA0/WKUP ------> UART4_TX
PA1 ------> UART4_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);
/* UART4 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspDeInit 1 */
/* USER CODE END UART4_MspDeInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11);
/* USART3 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
usart.h
/**
******************************************************************************
* File Name : USART.h
* Description : This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __usart_H
#define __usart_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include "cmsis_os2.h"
#define uartBufLength 2046
#define uartMsgBufLength 6
/* USER CODE END Includes */
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN Private defines */
extern uint8_t ustart3RdChar;
extern uint8_t uart4RdChar;
/* USER CODE END Private defines */
void MX_UART4_Init(void);
void MX_USART1_UART_Init(void);
void MX_USART3_UART_Init(void);
/* USER CODE BEGIN Prototypes */
typedef struct
{
uint16_t dataLength;
uint8_t packdata[uartBufLength];
}uartPack;
extern osSemaphoreId_t uart3RcvID;
extern uartPack uart3_MsgRcvBuf[uartMsgBufLength];
//extern uint8_t W25QXX_BUFFER[4096];
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ usart_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
spi.c
/**
******************************************************************************
* File Name : SPI.c
* Description : This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "spi.h"
/* USER CODE BEGIN 0 */
void SPI5_SetSpeed(uint8_t SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
__HAL_SPI_DISABLE(&hspi5); //关闭SPI
hspi5.Instance->CR1&=0XFFC7; //位3-5清零,用来设置波特率
hspi5.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
__HAL_SPI_ENABLE(&hspi5); //使能SPI
}
//SPI5 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
uint8_t SPI5_ReadWriteByte(uint8_t TxData)
{
uint8_t Rxdata;
HAL_SPI_TransmitReceive(&hspi5,&TxData,&Rxdata,1, 1000);
return Rxdata; //返回收到的数据
}
uint8_t SPI4_ReadWriteByte(uint8_t TxData)
{
uint8_t Rxdata;
HAL_SPI_TransmitReceive(&hspi4,&TxData,&Rxdata,1, 1000);
return Rxdata; //返回收到的数据
}
/* USER CODE END 0 */
SPI_HandleTypeDef hspi4;
SPI_HandleTypeDef hspi5;
/* SPI4 init function */
void MX_SPI4_Init(void)
{
hspi4.Instance = SPI4;
hspi4.Init.Mode = SPI_MODE_MASTER;
hspi4.Init.Direction = SPI_DIRECTION_2LINES;
hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi4.Init.NSS = SPI_NSS_SOFT;
hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi4.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi4) != HAL_OK)
{
Error_Handler();
}
}
/* SPI5 init function */
void MX_SPI5_Init(void)
{
hspi5.Instance = SPI5;
hspi5.Init.Mode = SPI_MODE_MASTER;
hspi5.Init.Direction = SPI_DIRECTION_2LINES;
hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi5.Init.NSS = SPI_NSS_SOFT;
hspi5.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi5.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi5) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI4)
{
/* USER CODE BEGIN SPI4_MspInit 0 */
/* USER CODE END SPI4_MspInit 0 */
/* SPI4 clock enable */
__HAL_RCC_SPI4_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/**SPI4 GPIO Configuration
PE2 ------> SPI4_SCK
PE5 ------> SPI4_MISO
PE6 ------> SPI4_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI4;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* USER CODE BEGIN SPI4_MspInit 1 */
/* USER CODE END SPI4_MspInit 1 */
}
else if(spiHandle->Instance==SPI5)
{
/* USER CODE BEGIN SPI5_MspInit 0 */
/* USER CODE END SPI5_MspInit 0 */
/* SPI5 clock enable */
__HAL_RCC_SPI5_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
/**SPI5 GPIO Configuration
PF7 ------> SPI5_SCK
PF8 ------> SPI5_MISO
PF9 ------> SPI5_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/* USER CODE BEGIN SPI5_MspInit 1 */
/* USER CODE END SPI5_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI4)
{
/* USER CODE BEGIN SPI4_MspDeInit 0 */
/* USER CODE END SPI4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI4_CLK_DISABLE();
/**SPI4 GPIO Configuration
PE2 ------> SPI4_SCK
PE5 ------> SPI4_MISO
PE6 ------> SPI4_MOSI
*/
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6);
/* USER CODE BEGIN SPI4_MspDeInit 1 */
/* USER CODE END SPI4_MspDeInit 1 */
}
else if(spiHandle->Instance==SPI5)
{
/* USER CODE BEGIN SPI5_MspDeInit 0 */
/* USER CODE END SPI5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI5_CLK_DISABLE();
/**SPI5 GPIO Configuration
PF7 ------> SPI5_SCK
PF8 ------> SPI5_MISO
PF9 ------> SPI5_MOSI
*/
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9);
/* USER CODE BEGIN SPI5_MspDeInit 1 */
/* USER CODE END SPI5_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
spi.h
/**
******************************************************************************
* File Name : SPI.h
* Description : This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __spi_H
#define __spi_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern SPI_HandleTypeDef hspi4;
extern SPI_HandleTypeDef hspi5;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_SPI4_Init(void);
void MX_SPI5_Init(void);
/* USER CODE BEGIN Prototypes */
extern uint8_t SPI4_ReadWriteByte(uint8_t TxData);
extern uint8_t SPI5_ReadWriteByte(uint8_t TxData);
extern void SPI5_SetSpeed(uint8_t SPI_BaudRatePrescaler);
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ spi_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
can.c
/**
******************************************************************************
* File Name : CAN.c
* Description : This file provides code for the configuration
* of the CAN instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "can.h"
/* USER CODE BEGIN 0 */
#include "delay.h"
#include "gpio.h"
CAN_TxHeaderTypeDef canTxMessage; //发送消息头
CAN_RxHeaderTypeDef canRxMessage; //接收消息头
canPack canRcvData[canBufLength] __attribute__((at(0xc0000400))); // Can 数据缓冲区
uint8_t canRcv_Wr = 0;
void CANFilterConfig_Scale32_IdMask_StandardIdOnly(void);
/****************************************************************************
File name: CAN.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
* 功能: CAN接收回调
* 调用者: MotorControlThread
* 调用
* 入口参数:CAN_HandleTypeDef *hcan
* 出口参数:无
****************************************************************************/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t rdData[8];
uint8_t i;
HAL_StatusTypeDef HAL_RetVal;
if(hcan ==&hcan1)
{
HAL_RetVal=HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &canRxMessage, rdData);
if ( HAL_OK==HAL_RetVal)
{
for (i=0;i<8;i++)
canRcvData[canRcv_Wr].packdata[i] = rdData[i];
osSemaphoreRelease(canRcvID);
canRcv_Wr++;
canRcv_Wr%=canBufLength;
}
}
}
HAL_StatusTypeDef sendTxMessage(uint8_t *pData,uint8_t offset)
{
uint32_t txMailBox;
uint8_t FreeTxmailBox=0;
HAL_StatusTypeDef HAL_RetVal;
FreeTxmailBox=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);
while(3!=FreeTxmailBox) // 等待CAN TX MAILBOX 空闲
{
osDelay(1); // CAN 故障 始终占据 线程休眠 释放总线
FreeTxmailBox=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);
}
HAL_RetVal = HAL_CAN_AddTxMessage(&hcan1,&canTxMessage,pData+offset,&txMailBox);
Delay_Us(200);
return HAL_RetVal;
}
/****************************************************************************
File name: CAN.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: CAN_SendData(uint16_t ID,uint8_t *pData,uint16_t Len)
* 功能: CAN发送数据帧
* 调用者: MotorControlThread
* 调用
* 入口参数:
uint16_t ID 帧Id号
uint8_t *pData 数据指针
uint16_t Len 数据长度
* 出口参数:0 成功 2 失败
****************************************************************************/
uint8_t CAN_SendData(uint16_t ID,uint8_t *pData,uint16_t Len)
{
//HAL_StatusTypeDef HAL_RetVal;
//uint8_t FreeTxNum=0;
uint8_t tryTime;
uint16_t SendTimes,SendCNT=0;
//uint32_t CAN_TX_MAILBOX;
SendTimes=Len/8+(Len%8?1:0);
//FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(&hcan1);
canTxMessage.RTR = CAN_RTR_DATA;
canTxMessage.IDE = CAN_ID_STD;
canTxMessage.StdId= ID;
canTxMessage.TransmitGlobalTime = DISABLE;
canTxMessage.DLC = 8;
while(SendTimes--)
{
if(0==SendTimes)
{
if(Len%8)
canTxMessage.DLC=Len%8;
}
tryTime = 0;
while (HAL_OK!= sendTxMessage(pData,SendCNT) && tryTime<5) tryTime++;
osDelay(1);
SendCNT+=8;
}
return 0;
}
/****************************************************************************
File name: CAN.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: CAN_Start
* 功能: CAN发送数据帧
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:0 成功 2 失败
****************************************************************************/
uint8_t CAN_Start(void)
{
/*CAN_FilterTypeDef CAN1_FilerConf;
CAN1_FilerConf.FilterIdHigh=0X0000; //32位ID
CAN1_FilerConf.FilterIdLow=0X0000;
CAN1_FilerConf.FilterMaskIdHigh=0X0000; //32位MASK
CAN1_FilerConf.FilterMaskIdLow=0X0000;
CAN1_FilerConf.FilterFIFOAssignment=CAN_FILTER_FIFO0;//过滤器0关联到FIFO0
CAN1_FilerConf.FilterBank=0; //过滤器0
CAN1_FilerConf.FilterMode=CAN_FILTERMODE_IDMASK;
CAN1_FilerConf.FilterScale=CAN_FILTERSCALE_32BIT;
CAN1_FilerConf.FilterActivation=ENABLE; //激活滤波器0
CAN1_FilerConf.SlaveStartFilterBank=14;
if(HAL_CAN_ConfigFilter(&hcan1,&CAN1_FilerConf)!=HAL_OK) return 2;//滤波器初始化*/
CANFilterConfig_Scale32_IdMask_StandardIdOnly();
// 启动 CAN
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
return 0;
}
/****************************************************************************
File name: CAN.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: CANFilterConfig_Scale32_IdMask_StandardIdOnly(void)
* 功能: 标准帧32位掩码配置 CAN1
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:无
****************************************************************************/
void CANFilterConfig_Scale32_IdMask_StandardIdOnly(void)
{
CAN_FilterTypeDef sFilterConfig;
/*uint16_t StdIdArray[10] ={0x7e0,0x7e1,0x7e2,0x7e3,0x7e4,
0x7e5,0x7e6,0x7e7,0x7e8,0x7e9}; //定义一组标准CAN ID */
//uint16_t mask,num,tmp,i;
uint16_t StdId = (DEVICE_ID<<4)|BOARD_ID;
sFilterConfig.FilterBank = 0; //使用过滤器0
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //配置为掩码模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //设置为32位宽
//sFilterConfig.FilterIdHigh =(StdIdArray[0]<<5); //使用StdIdArray[0]作为验证码
//sFilterConfig.FilterIdLow =0;
sFilterConfig.FilterIdHigh =((int32_t)StdId<<21&0xffff0000)>>16;
sFilterConfig.FilterIdLow =((int32_t)StdId<<21)|CAN_ID_STD|CAN_RTR_DATA;
/*mask =0x7ff; //下面开始计算屏蔽码
num =sizeof(StdIdArray)/sizeof(StdIdArray[0]);
for(i =0; i<num; i++) //屏蔽码位StdIdArray[]数组中所有成员的同或结果
{
tmp =StdIdArray[i] ^ (~StdIdArray[0]); //所有数组成员与第0个成员进行同或操作
mask &=tmp;
}
sFilterConfig.FilterMaskIdHigh =(mask<<5);
sFilterConfig.FilterMaskIdLow =0|0x02; //只接收数据帧 */
sFilterConfig.FilterMaskIdHigh =0xffff;
sFilterConfig.FilterMaskIdLow =0xffff;
sFilterConfig.FilterFIFOAssignment = 0; //设置通过的数据帧进入到FIFO0中
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}
/****************************************************************************
File name: CAN.C
Author: Wangyong Version: 1.0 Date: 2020-04-14
* 名称: CANFilterConfig_Scale16_IdList(void)
* 功能: 标准帧16位列表配置 CAN1
* 调用者: MotorControlThread
* 调用
* 入口参数:无
* 出口参数:无
****************************************************************************/
static void CANFilterConfig_Scale16_IdList(void)
{
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0; //使用过滤器0
sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; //设为列表模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; //位宽设置为16位
sFilterConfig.FilterIdHigh = BOARD_ID<<5; //4个标准CAN ID分别放入到4个存储中
sFilterConfig.FilterIdLow = (BOARD_ID|0x1)<<5;
sFilterConfig.FilterMaskIdHigh = (BOARD_ID|0x2)<<5;
sFilterConfig.FilterMaskIdLow = (BOARD_ID|0x3)<<5;
sFilterConfig.FilterFIFOAssignment = 0; //接收到的报文放入到FIFO0中
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE END 0 */
CAN_HandleTypeDef hcan1;
/* CAN1 init function */
void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 6;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_3TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_11TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_3TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = ENABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
}
void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* CAN1 clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* CAN1 interrupt Init */
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */
}
}
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{
if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspDeInit 0 */
/* USER CODE END CAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
/* CAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspDeInit 1 */
/* USER CODE END CAN1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
can.h
/**
******************************************************************************
* File Name : CAN.h
* Description : This file provides code for the configuration
* of the CAN instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __can_H
#define __can_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include "cmsis_os2.h"
#define canBufLength 32
typedef struct
{
CAN_RxHeaderTypeDef packHead;
uint8_t packdata[8];
}canPack;
extern CAN_HandleTypeDef hcan1;
extern CAN_TxHeaderTypeDef canTxMessage; //发送消息头
extern CAN_RxHeaderTypeDef canRxMessage; //接收消息头
extern osSemaphoreId_t canRcvID;
/* USER CODE END Includes */
extern CAN_HandleTypeDef hcan1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_CAN1_Init(void);
/* USER CODE BEGIN Prototypes */
extern uint8_t CAN_Start(void);
extern uint8_t CAN_SendData(uint16_t ID,uint8_t *pData,uint16_t Len);
extern canPack canRcvData[canBufLength]; // Can 数据缓冲区
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ can_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/