A板----------------
.ioc
malloc.c
#include "malloc.h" //内存池(32字节对齐)
__align(32) u8 membase[MEM_MAX_SIZE] __attribute__((at(0XC0000000))); //外部SDRAM内存池,前面2M给LTDC用了(1280*800*2)
//内存管理表 //内部SRAM内存池MAP
u32 memmapbase[MEM_ALLOC_TABLE_SIZE] __attribute__((at(0XC0000000+MEM_MAX_SIZE))); //外部SRAM内存池MAP
//内存管理参数
const u32 memtblsize=MEM_ALLOC_TABLE_SIZE; //内存表大小
const u32 memblksize=MEM_BLOCK_SIZE; //内存分块大小
const u32 memsize=MEM_MAX_SIZE; //内存总大小//内存管理控制器
struct _m_mallco_dev mallco_dev=
{my_mem_init, //内存初始化my_mem_perused, //内存使用率membase, //内存池memmapbase, //内存管理状态表0 //内存管理未就绪
};
//复制内存
//*des:目的地址
//*src:源地址
//n:需要复制的内存长度(字节为单位)
void mymemcpy(void *des,void *src,u32 n)
{ u8 *xdes=des;u8 *xsrc=src; while(n--)*xdes++=*xsrc++;
}
//设置内存
//*s:内存首地址
//c :要设置的值
//count:需要设置的内存大小(字节为单位)
void mymemset(void *s,u8 c,u32 count)
{ u8 *xs = s; while(count--)*xs++=c;
}
//内存管理初始化
//memx:所属内存块
void my_mem_init(void)
{ mymemset(mallco_dev.memmap,0,memtblsize*4); //内存状态表数据清零 mallco_dev.memrdy=1; //内存管理初始化OK
}
//获取内存使用率
//memx:所属内存块
//返回值:使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
u16 my_mem_perused(void)
{ u32 used=0; u32 i; for(i=0;i<memtblsize;i++) { if(mallco_dev.memmap[i])used++; } return (used*1000)/(memtblsize);
}
//内存分配(内部调用)
//memx:所属内存块
//size:要分配的内存大小(字节)
//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
u32 my_mem_malloc(u32 size)
{ signed long offset=0; u32 nmemb; //需要的内存块数 u32 cmemb=0;//连续空内存块数u32 i; if(!mallco_dev.memrdy)my_mem_init();//未初始化,先执行初始化 if(size==0)return 0XFFFFFFFF;//不需要分配nmemb=size/memblksize; //获取需要分配的连续内存块数if(size%memblksize)nmemb++; for(offset=memtblsize-1;offset>=0;offset--)//搜索整个内存控制区 { if(!mallco_dev.memmap[offset])cmemb++;//连续空内存块数增加else cmemb=0; //连续内存块清零if(cmemb==nmemb) //找到了连续nmemb个空内存块{for(i=0;i<nmemb;i++) //标注内存块非空 { mallco_dev.memmap[offset+i]=nmemb; } return (offset*memblksize);//返回偏移地址 }} return 0XFFFFFFFF;//未找到符合分配条件的内存块
}
//释放内存(内部调用)
//memx:所属内存块
//offset:内存地址偏移
//返回值:0,释放成功;1,释放失败;
u8 my_mem_free(u32 offset)
{ int i; if(!mallco_dev.memrdy)//未初始化,先执行初始化{my_mem_init(); return 1;//未初始化 } if(offset<memsize)//偏移在内存池内. { int index=offset/memblksize; //偏移所在内存块号码 int nmemb=mallco_dev.memmap[index]; //内存块数量for(i=0;i<nmemb;i++) //内存块清零{ mallco_dev.memmap[index+i]=0; } return 0; }else return 2;//偏移超区了.
}
//释放内存(外部调用)
//memx:所属内存块
//ptr:内存首地址
void myfree(void *ptr)
{ u32 offset; if(ptr==NULL)return;//地址为0. offset=(u32)ptr-(u32)mallco_dev.membase; my_mem_free(offset); //释放内存
}
//分配内存(外部调用)
//memx:所属内存块
//size:内存大小(字节)
//返回值:分配到的内存首地址.
void *mymalloc(u32 size)
{ u32 offset; offset=my_mem_malloc(size); if(offset==0XFFFFFFFF)return NULL; else return (void*)((u32)mallco_dev.membase+offset);
}
//重新分配内存(外部调用)
//memx:所属内存块
//*ptr:旧内存首地址
//size:要分配的内存大小(字节)
//返回值:新分配到的内存首地址.
void *myrealloc(void *ptr,u32 size)
{ u32 offset; offset=my_mem_malloc(size); if(offset==0XFFFFFFFF)return NULL; else { mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size); //拷贝旧内存内容到新内存 myfree(ptr); //释放旧内存return (void*)((u32)mallco_dev.membase+offset); //返回新内存首地址}
}
malloc.h
#ifndef __MALLOC_H
#define __MALLOC_H
#include "sys.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//内存管理 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/13
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
// #ifndef NULL
#define NULL 0
#endif//mem2内存参数设定.mem2的内存池处于外部SDRAM里面
#define MEM_BLOCK_SIZE 64 //内存块大小为64字节
#define MEM_MAX_SIZE (30840 *1024) //最大管理内存32263K
#define MEM_ALLOC_TABLE_SIZE MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小//内存管理控制器
struct _m_mallco_dev
{void (*init)(void); //初始化u16 (*perused)(void); //内存使用率u8 *membase; //内存池 管理SRAMBANK个区域的内存u32 *memmap; //内存管理状态表u8 memrdy; //内存管理是否就绪
};
extern struct _m_mallco_dev mallco_dev; //在mallco.c里面定义void mymemset(void *s,u8 c,u32 count); //设置内存
void mymemcpy(void *des,void *src,u32 n);//复制内存
void my_mem_init(void); //内存管理初始化函数(外/内部调用)
u32 my_mem_malloc(u32 size); //内存分配(内部调用)
u8 my_mem_free(u32 offset); //内存释放(内部调用)
u16 my_mem_perused(void) ; //获得内存使用率(外/内部调用)
//用户调用函数
void myfree(void *ptr); //内存释放(外部调用)
void *mymalloc(u32 size); //内存分配(外部调用)
void *myrealloc(void *ptr,u32 size);//重新分配内存(外部调用)
#endif
bsp.c
#include "bsp.h"
/*
*********************************************************************************************************
* 函 数 名: bsp_Init
* 功能说明: 初始化硬件设备。只需要调用一次。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。
* 全局变量。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_Init(void)
{SDRAM_Initialization_Sequence(&hsdram1);/*SDRAM初始化*/my_mem_init(); //初始化外部内存池
// bsp_InitUart(); /* 初始化串口 */
// bsp_CAN_Init();
// bsp_flashInit(); /*flash 读取存储的温度*///bsp_InitSram(); /* 初始sram 测试 */
//bsp_Initcan(); /* 初始can1 */HAL_TIM_Base_Start_IT(&htim4); //启动定时器TIM3
}
bsp.h
/*
*********************************************************************************************************
*
* 模块名称 : 驱动模块
* 文件名称 : bsp.h
* 版 本 : V1.0
* 说 明 : 头文件
*
*
*********************************************************************************************************
*/
#ifndef __BSP_H__
#define __BSP_H__#include <string.h>
#include <stdio.h>
#include "stm32f4xx_hal.h"
#include "main.h"
#include "looplist.h"
#include "sys.h"
#include "app_main.h"
//#include "epos_thread.h"
//#include "motor_thread.h"
//#include "smc_thread.h"
//#include "bsp_modbushost.h"
//#include "bsp_modbusslave.h"
#include "main_thread.h"
#include "led_thread.h"
//#include "bsp_epos2.h"
//#include "sys_stru.h"//#include "bsp_DWT.h"
//#include "pub_delay.h"//#include "bsp_spi.h"
//#include "bsp_w25qxx.h"
#include "bsp_led.h"
//#include "bsp_usart.h"
//#include "bsp_can.h"
//#include "bsp_interflash.h"
#include "bsp_sdram.h"
#include "malloc.h"
#include "tim.h"
#include "canopen_drv.h"
/* 供外部调用的函数声明 */
void bsp_Init(void);#endif
app_main.c
#include "bsp.h"
#include "cmsis_os2.h"
#include "app_main.h"/* 任务句柄 */
osThreadId_t main_ids = NULL;
osThreadId_t led_ids = NULL;
osThreadId_t cantx_ids = NULL;
osThreadId_t canrx_ids = NULL;
/*timer*/
osTimerId_t timer0_id;
osTimerId_t timer1_id;
osTimerId_t timer2_id;/*semaphore*/
osSemaphoreId_t sid_Semaphore_softtimer0;
osSemaphoreId_t sid_Semaphore_softtimer1;
osSemaphoreId_t sid_Semaphore_softtimer2;/*event*/
osEventFlagsId_t mid_event_Inited;/*queue*/
osMessageQueueId_t mid_MsgQueue_usart1_rx;
osMessageQueueId_t mid_MsgQueue_Set_temperature;
osMessageQueueId_t mid_MsgQueue_feedbak_temperature;
osMessageQueueId_t mid_MsgQueue_usart1_rx_falshupdata;
osMessageQueueId_t osMQId_Can1Tx;
osMessageQueueId_t osMQId_Can1Rx;unsigned short TimeOut=0;/*----------------------------------------------------------------------------
Initilise main thread*---------------------------------------------------------------------------*/static osThreadAttr_t ThreadAttr_MAIN = {.name = "Main_Thread", ///< name of the thread .attr_bits =NULL, ///< attribute bits.cb_mem=NULL, ///< memory for control block.cb_size=NULL, ///< size of provided memory for control block
//.stack_mem=NULL, ///< memory for stack.stack_size =THREAD_MAIN_SIZE,///< size of stack.priority=osPriorityNormal, ///< initial thread priority (default: osPriorityNormal).tz_module=NULL, ///< TrustZone module identifier.reserved=NULL, ///< reserved (must be 0)
};/*----------------------------------------------------------------------------
Initilise led thread*---------------------------------------------------------------------------*/static osThreadAttr_t ThreadAttr_LED = {.name = "LED_Thread", ///< name of the thread .attr_bits =NULL, ///< attribute bits.cb_mem=NULL, ///< memory for control block.cb_size=NULL, ///< size of provided memory for control block
//.stack_mem=NULL, ///< memory for stack.stack_size =THREAD_LED_SIZE,///< size of stack.priority=osPriorityNormal, ///< initial thread priority (default: osPriorityNormal).tz_module=NULL, ///< TrustZone module identifier.reserved=NULL, ///< reserved (must be 0)
};/*----------------------------------------------------------------------------
Initilise cansend thread*---------------------------------------------------------------------------*/static osThreadAttr_t ThreadAttr_CanTx = {.name = "CanSend_Thread", ///< name of the thread .attr_bits =NULL, ///< attribute bits.cb_mem=NULL, ///< memory for control block.cb_size=NULL, ///< size of provided memory for control block
//.stack_mem=NULL, ///< memory for stack.stack_size =THREAD_CANTX_SIZE,///< size of stack.priority=osPriorityNormal, ///< initial thread priority (default: osPriorityNormal).tz_module=NULL, ///< TrustZone module identifier.reserved=NULL, ///< reserved (must be 0)
};/*----------------------------------------------------------------------------
Initilise canrecive thread*---------------------------------------------------------------------------*/static osThreadAttr_t ThreadAttr_CanRx = {.name = "CanRecive_Thread", ///< name of the thread .attr_bits =NULL, ///< attribute bits.cb_mem=NULL, ///< memory for control block.cb_size=NULL, ///< size of provided memory for control block
//.stack_mem=NULL, ///< memory for stack.stack_size =THREAD_CANRX_SIZE,///< size of stack.priority=osPriorityNormal, ///< initial thread priority (default: osPriorityNormal).tz_module=NULL, ///< TrustZone module identifier.reserved=NULL, ///< reserved (must be 0)
};/*
*********************************************************************************************************
* 函 数 名: AppTaskCreate
* 功能说明: 创建应用任务
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/static void AppTaskCreate (void)
{//main_taskThreadAttr_MAIN.stack_mem = mymalloc(THREAD_MAIN_SIZE);main_ids=osThreadNew(main_task, NULL, &ThreadAttr_MAIN);//led_taskThreadAttr_LED.stack_mem = mymalloc(THREAD_LED_SIZE);led_ids=osThreadNew(led_task, NULL, &ThreadAttr_LED);//canrx_taskThreadAttr_CanTx.stack_mem = mymalloc(THREAD_CANTX_SIZE);canrx_ids=osThreadNew(thread_canopen_rx, NULL, &ThreadAttr_CanRx);//cantx_taskThreadAttr_CanRx.stack_mem = mymalloc(THREAD_CANRX_SIZE);cantx_ids=osThreadNew(thread_canopen_tx, NULL, &ThreadAttr_CanTx);
}/*
*********************************************************************************************************
* 函 数 名: AppObjCreate
* 功能说明: 创建任务通信机制
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static const osEventFlagsAttr_t EventFlagAttr_InitedAll= {.name = "InitedAll_Events",
};static const osTimerAttr_t timerAttr_timer0 = {.name = "timer_0",
};
static const osTimerAttr_t timerAttr_timer1 = {.name = "timer_1",
};
static const osTimerAttr_t timerAttr_timer2 = {.name = "timer_2",
};
//软件定时器0中断回调函数
void timer0_callback(void *param)
{osSemaphoreRelease(sid_Semaphore_softtimer0);//100mSif(TimeOut){TimeOut--;}
}
//软件定时器1中断回调函数
void time1_callback(void *param)
{osSemaphoreRelease(sid_Semaphore_softtimer1);
}
//软件定时器2中断回调函数
void timer2_callback(void *param)
{osSemaphoreRelease(sid_Semaphore_softtimer2);
}/*----------------------------------------------------------------------------
Initilise Can1Tx_messageque*---------------------------------------------------------------------------*/
static osMessageQueueAttr_t QueMessageAttr_Can1Tx={.name = "TxMessageQue",.mq_size = QUE_MESSAGE_COM_SIZE,//.mq_mem = NULL,
};
/*----------------------------------------------------------------------------
Initilise Can1Rx_messageque*---------------------------------------------------------------------------*/
static osMessageQueueAttr_t QueMessageAttr_Can1Rx={.name = "RxMessageQue",.mq_size = QUE_MESSAGE_COM_SIZE,//.mq_mem = NULL,
};/*----------------------------------------------------------------------------* Message Queue creation & usage* Initilise the LED's, Create the semaphore *---------------------------------------------------------------------------*/
int AppObjCreate (void)
{/*timer*/timer0_id = osTimerNew(&timer0_callback, osTimerPeriodic,(void *)0, &timerAttr_timer0); //软件定时器timer0 200msif (timer0_id == NULL){return -1;}timer1_id = osTimerNew(&time1_callback, osTimerPeriodic,(void *)0, &timerAttr_timer1); //软件定时器timer1 1Sif (timer1_id == NULL){return -1;}timer2_id = osTimerNew(&timer2_callback, osTimerPeriodic,(void *)0, &timerAttr_timer2); //软件定时器timer2 1Sif (timer2_id == NULL){return -1;}osTimerStart(timer0_id, 100);//启动系统软件定时器/*semaphore*/sid_Semaphore_softtimer0 = osSemaphoreNew(1, 0, NULL );if(sid_Semaphore_softtimer0 == NULL){return -1;}sid_Semaphore_softtimer1 = osSemaphoreNew(1, 0, NULL ); if(sid_Semaphore_softtimer1 == NULL){return -1;}sid_Semaphore_softtimer2 = osSemaphoreNew(1, 0, NULL ); if(sid_Semaphore_softtimer2 == NULL){return -1;}/*queue*/mid_MsgQueue_Set_temperature = osMessageQueueNew(msgQUEUE_ITEM,sizeof(temp_set_t), NULL);if (mid_MsgQueue_Set_temperature == NULL) {return -1;}mid_MsgQueue_usart1_rx = osMessageQueueNew(can_Rx_frame_item,sizeof(loopData_Typedef), NULL); //深度can_Rx_frame_itemif (mid_MsgQueue_usart1_rx == NULL) {return -1;} //feedbackmid_MsgQueue_feedbak_temperature = osMessageQueueNew(msgQUEUE_ITEM,sizeof(fb_TEMP_t), NULL);if (mid_MsgQueue_feedbak_temperature == NULL) {return -1; // Message Queue object not created, handle failure}//flash 升级接受数据使用mid_MsgQueue_usart1_rx_falshupdata = osMessageQueueNew(falshUpdata_Rx_frame_item,sizeof(loopData_Typedef), NULL);if (falshUpdata_Rx_frame_item == NULL) {return -1;} /*event*/mid_event_Inited = osEventFlagsNew (&EventFlagAttr_InitedAll);//所有初始化完成//通讯QueMessageAttr_Can1Tx.mq_mem = mymalloc(QUE_MESSAGE_COM_SIZE);osMQId_Can1Tx = osMessageQueueNew(msgQUEUE_ITEM,256, &QueMessageAttr_Can1Tx);if (osMQId_Can1Tx == NULL) {return -1;}QueMessageAttr_Can1Rx.mq_mem = mymalloc(QUE_MESSAGE_COM_SIZE);osMQId_Can1Rx = osMessageQueueNew(msgQUEUE_ITEM,256, &QueMessageAttr_Can1Rx);if (osMQId_Can1Rx == NULL) {return -1;} return (0);
}uint8_t *p_test;
void app_main (void const* arg)
{// osStatus_t status;/* 创建任务通信机制 */AppObjCreate();/* 创建任务 */AppTaskCreate();#ifdef SDRAM_TESTp_test=mymalloc(SRAMEX,THREAD_MAIN_SIZE);for(uint16_t i=0;i<2048;i++)*(p_test+i)=i;__NOP();myfree(SRAMEX,p_test);p_test=mymalloc(SRAMEX,20);#endifwhile(1) { if(TimeOut==0){TimeOut=2;LED_RUN_Toggle();} }}
app_main.h
#ifndef __APP_MAIN_H__
#define __APP_MAIN_H__
#include "cmsis_os2.h" #define msgQUEUE_ITEM 5#define falshUpdata_Rx_frame_len 1024 /* 数据帧长度 */
#define falshUpdata_Rx_frame_item 4 /* 数据帧条数 */
#define falshUpdata_FRAME_MAX_SIZE (falshUpdata_Rx_frame_len*falshUpdata_Rx_frame_item) /*需要开辟在缓冲区4K Byte数*/#define can_Rx_frame_len 8 /* 数据帧长度 */
#define can_Rx_frame_item 50 /* 数据帧条数 */
#define can_FRAME_MAX_SIZE (can_Rx_frame_len*can_Rx_frame_item) /*需要开辟在缓冲区400Byte数*//*
分配线程堆栈空间大小
*/
#define QUE_MESSAGE_COM_SIZE 1024
#define THREAD_MAIN_SIZE 2048
#define THREAD_LED_SIZE 2048
#define THREAD_CANTX_SIZE 2048
#define THREAD_CANRX_SIZE 2048
typedef struct
{uint16_t addr;uint16_t en;uint16_t temp;
}temp_set_t;typedef struct{uint16_t time;uint16_t temperature_PE;uint16_t temperature_FAN;uint16_t work_status;uint16_t error;
}fb_TEMP_t;/*semaphore*/
extern osSemaphoreId_t sid_Semaphore_softtimer0;
extern osSemaphoreId_t sid_Semaphore_softtimer1;
extern osSemaphoreId_t sid_Semaphore_softtimer2;
/*queue*/
extern osMessageQueueId_t mid_MsgQueue_usart1_rx;
extern osMessageQueueId_t mid_MsgQueue_feedbak_temperature;
extern osMessageQueueId_t mid_MsgQueue_Set_temperature;
extern osMessageQueueId_t mid_MsgQueue_usart1_rx_falshupdata;
extern osMessageQueueId_t osMQId_Can1Tx;
extern osMessageQueueId_t osMQId_Can1Rx;
/*event*/
//extern osEventFlagsId_t mid_event_Inited;
/*timer*/
extern osTimerId_t timer0_id;//200ms 定时器PID计算
extern osTimerId_t timer1_id;//1S 显示时间
extern osTimerId_t timer2_id;
/* 供外部调用的函数声明 */
static void AppTaskCreate (void);
int AppObjCreate (void);#endif
main_thread.c
#include "main_thread.h"
void main_task (void * arg)
{while(1){osDelay(1);osThreadYield();}
}
main_thread.h
#ifndef __MAIN_THREAD_H
#define __MAIN_THREAD_H
#include "stm32f4xx_hal.h"
#include "cmsis_os2.h"
#include "app_main.h"
void main_task (void * arg);#endif
bsp_sdram.c
#include "bsp_sdram.h"
#include "sys.h"
#include "fmc.h"
#include "delay.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//SDRAM驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
////发送SDRAM初始化序列
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{u32 temp=0;//SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAMSDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0); //时钟配置使能Delay_Us(500);
// HAL_Delay(1000); //至少延时200usSDRAM_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=(u32)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的模式寄存器//刷新频率计数器(以SDCLK频率计数),计算方法://COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数//我们使用的SDRAM刷新周期为64ms,SDCLK=180/2=90Mhz,行数为8192(2^13).//所以,COUNT=64*1000*90/8192-20=683HAL_SDRAM_ProgramRefreshRate(&hsdram1,683);}//向SDRAM发送命令
//bankx:0,向BANK5上面的SDRAM发送指令
// 1,向BANK6上面的SDRAM发送指令
//cmd:指令(0,正常模式/1,时钟配置使能/2,预充电所有存储区/3,自动刷新/4,加载模式寄存器/5,自刷新/6,掉电)
//refresh:自刷新次数
//regval:模式寄存器的定义
//返回值:0,正常;1,失败.
u8 SDRAM_Send_Cmd(u8 bankx,u8 cmd,u8 refresh,u16 regval)
{u32 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;
}//在指定地址(WriteAddr+Bank5_SDRAM_ADDR)开始,连续写入n个字节.
//pBuffer:字节指针
//WriteAddr:要写入的地址
//n:要写入的字节数
void FMC_SDRAM_WriteBuffer(u8 *pBuffer,u32 WriteAddr,u32 n)
{for(;n!=0;n--){*(vu8*)(Bank5_SDRAM_ADDR+WriteAddr)=*pBuffer;WriteAddr++;pBuffer++;}
}//在指定地址((WriteAddr+Bank5_SDRAM_ADDR))开始,连续读出n个字节.
//pBuffer:字节指针
//ReadAddr:要读出的起始地址
//n:要写入的字节数
void FMC_SDRAM_ReadBuffer(u8 *pBuffer,u32 ReadAddr,u32 n)
{for(;n!=0;n--){*pBuffer++=*(vu8*)(Bank5_SDRAM_ADDR+ReadAddr);ReadAddr++;}
}
bsp_sdram.h
#ifndef _SDRAM_H_
#define _SDRAM_H_
#include "sys.h"
#include "stm32f4xx_hal.h"
#include "fmc.h"
#ifndef _SDRAM_H
#define _SDRAM_H//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//SDRAM驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/6
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
// #define Bank5_SDRAM_ADDR ((u32)(0XC0000000)) //SDRAM开始地址//SDRAM配置参数
#define SDRAM_MODEREG_BURST_LENGTH_1 ((u16)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((u16)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((u16)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((u16)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((u16)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((u16)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((u16)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((u16)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((u16)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((u16)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((u16)0x0200)void SDRAM_MPU_Config(void);
u8 SDRAM_Send_Cmd(u8 bankx,u8 cmd,u8 refresh,u16 regval);
void FMC_SDRAM_WriteBuffer(u8 *pBuffer,u32 WriteAddr,u32 n);
void FMC_SDRAM_ReadBuffer(u8 *pBuffer,u32 ReadAddr,u32 n);
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram);
#endif#endif
bsp_can.h
#ifndef _BSP_CAN_H
#define _BSP_CAN_H#include "main.h"
#define CANOPEN_TIM_PERIOD 100typedef struct
{CAN_TxHeaderTypeDef Header;uint8_t Data[8];
}CanTxMsg_t;
typedef struct
{CAN_RxHeaderTypeDef Header;uint8_t Data[8];
}CanRxMsg_t;#endif
canopen_drv.c
#include "canopen_drv.h"
#include "DPCRMaster.h"
#include "bsp_can.h"
#include "tim.h"
#include "can.h"
#include "app_main.h"CanTxMsg_t CAN1_TxMsg;
CanRxMsg_t CAN1_RxMsg;
uint32_t TxMailbox = CAN_TX_MAILBOX1;/*定时器相关变量*/
static TIMEVAL laster_counter_val = 0;
static TIMEVAL elapsed_time = 0;void thread_canopen_rx(void *arg)
{static CanRxMsg_t CAN1_RxMsg;static Message msg;uint8_t i=0;while(1){if(osOK == osMessageQueueGet(osMQId_Can1Rx,&CAN1_RxMsg,NULL,100))//从can接收消息队列中获取内容{msg.cob_id = CAN1_RxMsg.Header.StdId;if(CAN_RTR_REMOTE == CAN1_RxMsg.Header.RTR)msg.rtr = 1;//远程帧elsemsg.rtr = 0;//数据帧msg.len = (UNS8)CAN1_RxMsg.Header.DLC;for(i=0;i<CAN1_RxMsg.Header.DLC;i++){msg.data[i] = CAN1_RxMsg.Data[i];}__HAL_TIM_DISABLE_IT(&htim_can,TIM_IT_UPDATE);canDispatch(&DPCRMaster_Data,&msg);//调用协议相关接口__HAL_TIM_DISABLE_IT(&htim_can,TIM_IT_UPDATE);}osDelay(1);}
}void thread_canopen_tx(void *arg)
{unsigned char nodeID=0x01;HAL_TIM_Base_Start(&htim_can);setNodeId(&DPCRMaster_Data,nodeID);//节点初始化setState(&DPCRMaster_Data,Initialisation);setState(&DPCRMaster_Data,Operational);while(1){if(osOK == osMessageQueueGet(osMQId_Can1Tx,&CAN1_TxMsg,NULL,100)){if(HAL_OK != HAL_CAN_AddTxMessage(&hcan1,&CAN1_TxMsg.Header,CAN1_TxMsg.Data,&TxMailbox)){osDelay(1);HAL_CAN_AddTxMessage(&hcan1,&CAN1_TxMsg.Header,CAN1_TxMsg.Data,&TxMailbox);}}osDelay(1);}
}//
unsigned char canSend(CAN_PORT notused,Message *m)
{uint8_t i;static CanTxMsg_t TxMsg;TxMsg.Header.StdId = m->cob_id;if(m->rtr)TxMsg.Header.RTR = CAN_RTR_REMOTE;elseTxMsg.Header.RTR = CAN_RTR_DATA;TxMsg.Header.IDE = CAN_ID_STD;TxMsg.Header.DLC = m->len;for(i=0;i<m->len;i++)TxMsg.Data[i]=m->data[i];if(osOK == osMessageQueueGet(osMQId_Can1Tx,&TxMsg,NULL,NULL)){return 0;}else{return 0xFF;}
}void setTimer(TIMEVAL value)
{uint32_t timer = __HAL_TIM_GetCounter(&htim_can); elapsed_time +=timer-laster_counter_val;laster_counter_val = CANOPEN_TIM_PERIOD - value;__HAL_TIM_SetCounter(&htim_can,CANOPEN_TIM_PERIOD - value);HAL_TIM_Base_Start(&htim_can);//TIM_Cmd(CANOPEN_TIMx,ENABLE);
}TIMEVAL getElapsedTime(void)
{uint32_t timer = __HAL_TIM_GetCounter(&htim_can);if(timer < laster_counter_val)timer += CANOPEN_TIM_PERIOD;TIMEVAL elapsed = timer - laster_counter_val + elapsed_time;return elapsed;
}void CanOpen_DispatchFromISR(void)
{laster_counter_val = 0;elapsed_time = 0;TimeDispatch();
}//定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(&htim_can == htim){CanOpen_DispatchFromISR();}
}
//CAN接收回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{if(hcan == &hcan1)//接收中断里把收到的数据放入消息队列中{HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&CAN1_RxMsg.Header,CAN1_RxMsg.Data);if(osOK == osMessageQueuePut(osMQId_Can1Rx,&CAN1_RxMsg,NULL,NULL)){;}else{Error_Handler();}}
}
canopen_drv.h
#ifndef _CANOPEN_DRV_H
#define _CANOPEN_DRV_H
#include "stm32f4xx_hal.h"
#include "cmsis_os2.h"
#include "app_main.h"void thread_canopen_rx(void *arg);
void thread_canopen_tx(void *arg);#endif
A板----------------相关推荐
- zeroclipboard 粘贴板的应用示例, 兼容 Chrome、IE等多浏览器
zeroclipboard单个复制按钮和多个复制按钮的实现方法 最近网站改版想让复制代码功能在多个浏览器上都可以实现,最近看网上不少说我们的代码复制功能不好用的,我们最近将会增加代码高亮等功能,希望大 ...
- 2022-2028年中国中密度纤维板市场投资分析及前景预测报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了中密度纤维板行业相关概述.中国中密度纤维板行业运行环境.分析了中国中 ...
- 2022-2028年中国塑料板的制造行业市场发展模式及竞争格局预测报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了塑料板的制造行业相关概述.中国塑料板的制造行业运行环境.分析了中国塑 ...
- 2022-2028年中国硅酸钙板行业市场研究及前瞻分析报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了硅酸钙板行业相关概述.中国硅酸钙板行业运行环境.分析了中国硅酸钙板行 ...
- 2022-2028年中国XPS挤塑板行业市场全景评估及产业前景规划报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了XPS挤塑板行业相关概述.中国XPS挤塑板行业运行环境.分析了中国X ...
- 编写可调模板并使用自动调谐器
编写可调模板并使用自动调谐器 这是TVM中自动调整模块的入门资料. 自动调整有两个步骤.第一步是定义搜索空间.第二步是运行搜索算法来探索这个空间.在本文中,可以学习如何在TVM中执行这两个步骤.整个工 ...
- 编写可调模板并使用Auto-tuner自动调谐器
编写可调模板并使用Auto-tuner自动调谐器 本文介绍在TVM自动调谐模块. 自动调谐有两个步骤.第一步是定义搜索空间.第二步是运行一个搜索算法来探索这个空间.可以学习如何在TVM中执行这两个步骤 ...
- Xilinx Zynq FPGA Boards板
Xilinx Zynq FPGA Boards板 Xilinx Zynq FPGA Boards 介绍 Styx是一个易于使用的Zynq开发模块,具有Xilinx的Zynq ZC7020 SoC和FT ...
- 基于uFUN开发板的心率计(一)DMA方式获取传感器数据
前言 从3月8号收到板子,到今天算起来,uFUN到手也有两周的时间了,最近利用下班后的时间,做了个心率计,从单片机程序到上位机开发,到现在为止完成的差不多了,实现很简单,uFUN开发板外加一个Puls ...
- 2022-2028年中国塑料网格板行业市场行情动态及发展趋向分析报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了塑料网格板行业相关概述.中国塑料网格板行业运行环境.分析了中国塑料网 ...
最新文章
- Python装饰器-装饰流程,执行顺序
- 基于python的界面自动化测试-基于Selenium+Python的web自动化测试框架
- Boost:双图bimap与mi_bidirectional地图的测试程序
- HDU4514(非连通图的环判断与图中最长链)
- [CSS] Use CSS Counters to Create Pure CSS Dynamic Lists
- 【CF1200E】Compress Words【kmp】
- JVM参数设置、分析
- python绘画梦想_用python实现你的绘画梦想
- 使用 Jupyter 近 2 年,发现了这 3 个实用技巧
- 用 C# 实现带键值的优先队列
- 数据结构笔记(十五)-- 数组原理
- EXCEL 2010学习笔记—— 动态图表
- Vijos P1423 最佳路线
- 联发科MT7621 Openwrt开发编译记录
- 51单片机之定时器/计数器0中断程序
- 计算机显卡型号中数字含义详解,显卡型号中字母和数字所代表的含义
- dejavu项目笔记
- 实战技法 - 短线操盘 (8)
- jupyter notebook 的 hinterland 插件 设置 代码提示但是默认不选中
- mysql 权限管理 针对表的字段 级别 授权 columns_priv表