本帖最后由 黄大队长 于 2019-6-29 22:03 编辑
基于UCOSIII操作系统函数发生器设计
相逢总有千言,离别仅需二字。出来工作半年多了,工作挺忙的。刚注册了这个网站,就看到了这个活动,挺欣慰的!作为一名初级电子工程师,就用开发板简单的做了一个波形发生器。
其主控使用STM32F4,DAC分辨率12位,幅度0-3.3V。由于工作时间限制,只能做简单的波形输出!
硬件: UCOS-III操作系统
STM32F4主频168MHZ
4.3寸FTF-LCD
12位DAC
按键切换波形输出
无线通讯串口LC12S
波特率9600,将系统数据传至电脑监测
当然,第一步先搭建UCOS-III操作系统环境。哈哈哈哈#include "stm32f4xx.h"
#include "sys.h"
#include "includes.h"
#include "os_app_hooks.h"
#include "usart.h"
#include "delay.h"
#include "MYTASK.H"
#include "lcd.h"
#include "key.h"
#include "RES.H"
#include "led.h"
#include "MOTOR.H"
#include "PULL.H"
#include "SHOES.H"
#include "INFORMATION.H"
#include "DAC.H"
/**************开始任务参数配置**********************************************************/
extern OS_TCB Start_Task_Lump; /*定义开始任务的任务块*/
extern CPU_STK Start_Task_Stack[Start_Stack_Size]; /*定义开始任务的堆栈*/
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] UCOSIII主程序
* [url=home.php?mod=space&uid=536309]@NOTE[/url]
* @param
* @retval None
*/
int main(void)
{
OS_ERR err; //错误类型结构体
CPU_SR_ALLOC(); //这是一个宏定义 将CPU状态寄存器的值保存起来
delay_init(168); //时钟初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
DAC_Output_Init(); //DAC通道初始化
Set_DAC1_OutputValue(0); //0V输出
uart_init(9600); //串口初始化
System_Start_Information(0);//系统正在初始化
Key_Init(); //按键初始化
Led_Init(); //LED初始化
LCD_Init(); //LCD初始化
LCD_Clear(WHITE); //白底
POINT_COLOR = BLACK; //黑字
LCD_ShowString(200,100,300,30,24,"STM32");
LCD_ShowString(100,130,300,30,24,"Simple Function Generator");
LCD_ShowString(190,160,300,30,24,"UCOS-III");
LCD_ShowString(180,200,200,30,24,"2019/06/24");
POINT_COLOR = RED; //红字
// ALL_PWM_Init(200-1,168-1);
// System_Res(); //上电后所有动作复位
OSInit(&err); //os.h os_core.c 初始化UCOSIII
CPU_CRITICAL_ENTER(); //cpu.h 进入临界区 任务调度加锁 教程121
OSTaskCreate ((OS_TCB *)&Start_Task_Lump, /*任务控制块*/
(CPU_CHAR *)"Start_Tack", /*任务名字*/
(OS_TASK_PTR )Start_Tack, /*任务函数*/
(void *)0, /*传递给任务函数的参数*/
(OS_PRIO )Start_Task_priority, /*任务优先级*/
(CPU_STK *)&Start_Task_Stack[0], /*任务堆栈基地址*/
(CPU_STK_SIZE )Start_Stack_Size/10, /*任务堆栈深度限位*/
(CPU_STK_SIZE )Start_Stack_Size, /*任务堆栈大小*/
(OS_MSG_QTY )0, /*任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息*/
(OS_TICK )0, /*当使能时间片轮转时的时间片长度,为0时为默认长度*/
(void *)0, /*用户补充的存储区*/
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, /*任务选项 可以在OS.H选择*/
(OS_ERR *)&err /*存放该函数错误时的返回值*/
);
CPU_CRITICAL_EXIT(); //cpu.h 退出临界区 任务调度解锁 教程121
System_Start_Information(1);//系统初始化完成
OSStart(&err); //UCOSIII开始运行
while(1);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT HuangShihao *****END OF FILE****/
#include "DAC.H"
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] DAC通道1初始化
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 用PA4作为模拟输出
* @param None
* @retval None
*/
void DAC_Output_Init(void)
{
GPIO_InitTypeDef GPIO_InitTypeDefStructure;
DAC_InitTypeDef DAC_InitTypeDefStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
GPIO_InitTypeDefStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitTypeDefStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitTypeDefStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
// GPIO_InitTypeDefStructure.GPIO_Speed = GPIO_Fast_Speed;
GPIO_Init(GPIOA,&GPIO_InitTypeDefStructure);
DAC_InitTypeDefStructure.DAC_Trigger = DAC_Trigger_None;//没有触发方式
DAC_InitTypeDefStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生
DAC_InitTypeDefStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;//要和波形发生一起用 这里不需要配置
DAC_InitTypeDefStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;//不使能输出缓存关闭
DAC_Init(DAC_Channel_1,&DAC_InitTypeDefStructure);
DAC_Cmd(DAC_Channel_1,ENABLE);//使能ADC1
DAC_SetChannel1Data(DAC_Align_12b_R,0);//右对齐方式 输出电压值为0
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] DAC通道1输出值
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 注意这里是12位输出格式 最大值为0-4096 但我们的参考电压为3.3v 因此请看@param注释
* @param ADC1_OutputValue 在这里选择范围为0-3300
* @retval None
*/
void Set_DAC1_OutputValue(u16 ADC1_OutputValue)
{
double ADC1_OutputValueTemp;
ADC1_OutputValueTemp = ((double)ADC1_OutputValue/1000)*4096/3.3;
DAC_SetChannel1Data(DAC_Align_12b_R,ADC1_OutputValueTemp);
}
/**
* @brief 获取DAC通道1的值
* @note None
* @param None
* @retval None
*/
float Read_DAC1_Data(void)
{
float OutputValue;
OutputValue = (float)DAC_GetDataOutputValue(DAC_Channel_1)*(3.3/4096);
return OutputValue;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT HuangShihao *****END OF FILE****/
void LCD_Init(void)
{
vu32 i=0;
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef readWriteTiming;
FSMC_NORSRAMTimingInitTypeDef writeTiming;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD,PE,PF,PG时钟
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PB15 推挽输出,控制背光
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 //PB15 推挽输出,控制背光
GPIO_InitStructure.GPIO_Pin = (3<<0)|(3<<4)|(7<<8)|(3<<14);//PD0,1,4,5,8,9,10,14,15 AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = (0X1FF<<7);//PE7~15,AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12
GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);//PE7,AF12
GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC);
GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12
GPIO_PinAFConfig(GPIOF,GPIO_PinSource12,GPIO_AF_FSMC);//PF12,AF12
GPIO_PinAFConfig(GPIOG,GPIO_PinSource12,GPIO_AF_FSMC);
readWriteTiming.FSMC_AddressSetupTime = 0XF; //地址建立时间(ADDSET)为16个HCLK 1/168M=6ns*16=96ns
readWriteTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间(ADDHLD)模式A未用到
readWriteTiming.FSMC_DataSetupTime = 60; //数据保存时间为60个HCLK =6*60=360ns
readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
readWriteTiming.FSMC_CLKDivision = 0x00;
readWriteTiming.FSMC_DataLatency = 0x00;
readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
writeTiming.FSMC_AddressSetupTime =9; //地址建立时间(ADDSET)为9个HCLK =54ns
writeTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间(A
writeTiming.FSMC_DataSetupTime = 8; //数据保存时间为6ns*9个HCLK=54ns
writeTiming.FSMC_BusTurnAroundDuration = 0x00;
writeTiming.FSMC_CLKDivision = 0x00;
writeTiming.FSMC_DataLatency = 0x00;
writeTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;// 这里我们使用NE4 ,也就对应BTCR[6],[7]。
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不复用数据地址
FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM; //SRAM
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; // 存储器写使能
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; // 读写使用不同的时序
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //读写时序
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming; //写时序
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); // 使能BANK1
第二步:创建任务/**
* [url=home.php?mod=space&uid=247401]@brief[/url] UCOSIII 开始任务
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 负责其他任务的创建
* @param
* @retval None
*/
void Start_Tack(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); /*打开统计任务*/
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN /*如果使能了测量中断关闭时间*/
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN /*当使用时间片轮转的时候*/
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); /*使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms*/
#endif
OS_CRITICAL_ENTER(); //进入临界区
/*Led指示任务*/
OSTaskCreate ((OS_TCB *)&Led_Task_Lump, /*任务控制块*/
(CPU_CHAR *)"Led_Tack", /*任务名字*/
(OS_TASK_PTR )Led_Tack, /*任务函数*/
(void *)0, /*传递给任务函数的参数*/
(OS_PRIO )Led_Task_priority, /*任务优先级*/
(CPU_STK *)&Led_Task_Stack[0], /*任务堆栈基地址*/
(CPU_STK_SIZE )Led_Stack_Size/10, /*任务堆栈深度限位*/
(CPU_STK_SIZE )Led_Stack_Size, /*任务堆栈大小*/
(OS_MSG_QTY )0, /*任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息*/
(OS_TICK )0, /*当使能时间片轮转时的时间片长度,为0时为默认长度*/
(void *)0, /*用户补充的存储区*/
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, /*任务选项 可以在OS.H选择*/
(OS_ERR *)&err /*存放该函数错误时的返回值*/
);
/*PullRod任务*/
OSTaskCreate ((OS_TCB *)&PullRod_Task_Lump, /*任务控制块*/
(CPU_CHAR *)"PullRod_Tack", /*任务名字*/
(OS_TASK_PTR )PullRod_Tack, /*任务函数*/
(void *)0, /*传递给任务函数的参数*/
(OS_PRIO )PullRod_Task_priority, /*任务优先级*/
(CPU_STK *)&PullRod_Task_Stack[0], /*任务堆栈基地址*/
(CPU_STK_SIZE )PullRod_Stack_Size/10, /*任务堆栈深度限位*/
(CPU_STK_SIZE )PullRod_Stack_Size, /*任务堆栈大小*/
(OS_MSG_QTY )0, /*任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息*/
(OS_TICK )0, /*当使能时间片轮转时的时间片长度,为0时为默认长度*/
(void *)0, /*用户补充的存储区*/
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, /*任务选项 可以在OS.H选择*/
(OS_ERR *)&err /*存放该函数错误时的返回值*/
);
OS_CRITICAL_EXIT(); //退出临界区
OSTaskDel((OS_TCB *)0, /*删除开始任务自身*/
(OS_ERR *)&err
);
}
到这一步就可以看到系统初始化成功数据打印至电脑,TFT-LCD显示系统界面:
第三步:利用任务调度输出方波、三脚波、锯齿波。(我这里只贴上方波的代码)并在TFT-LCD显示器上显示波形。
/**
* @brief led任务
* @note
* @param
* @retval None
*/
void Led_Tack(void *p_arg)
{
u16 Hight;
OS_ERR err;
CPU_SR_ALLOC(); //这是一个宏定义 将CPU状态寄存器的值保存起来
p_arg = p_arg;
OS_CRITICAL_ENTER(); //进入临界区
OS_CRITICAL_EXIT(); //退出临界区
while(1)
{
//方波
if(Wave_Direction == 0)
{
Wave_Out = 0;
Wave_Direction = 1;
Wave_Dis = 800;
}
else
{
Wave_Out = 3000;
Wave_Direction = 0;
Wave_Dis = 400;
}
TFT-LCD显示器上显示波形:
利用优利德110MH示波器进行显示结果:
经历两个夜晚的战斗,只能完成一些简单的功能。希望大家多多支持,互相学习!
2019.06.29
于深圳龙岗
黄大队长 编
|
打赏榜单
小小电子爱好者 打赏了 0.20 元 2019-06-29 理由:支持
共1人点赞
|
不错 来自山东人民的祝福