完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
原理
STM32ADC采样,我选用PA5作为ADC接口,并做了UI设计。 KEY配置 key.c #include "key.h" #include "SysTick.h" //按键初始化函数 void KEY_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOA,ENABLE); //使能端口时钟 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN; //输入模式 GPIO_InitStructure.GPIO_Pin=KEY_LEFT_Pin|KEY_DOWN_Pin|KEY_RIGHT_Pin;//管脚设置 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉 GPIO_Init(KEY_Port,&GPIO_InitStructure); //初始化结构体 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN; //输入模式 GPIO_InitStructure.GPIO_Pin=KEY_UP_Pin;//管脚设置 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉 GPIO_Init(KEY_UP_Port,&GPIO_InitStructure); //初始化结构体 } //mode=0:单次按下按键 //mode=1:连续按下按键 //返回值:0表示未有按键按下 u8 KEY_Scan(u8 mode) { static u8 key=1; if(key==1&&(K_UP==1||K_DOWN==0||K_LEFT==0||K_RIGHT==0)) //任意一个按键按下 { delay_ms(10); //消抖 key=0; if(K_UP==1) { return KEY_UP; } else if(K_DOWN==0) { return KEY_DOWN; } else if(K_LEFT==0) { return KEY_LEFT; } else { return KEY_RIGHT; } } else if(K_UP==0&&K_DOWN==1&&K_LEFT==1&&K_RIGHT==1) //无按键按下 { key=1; } if(mode==1) //连续按键按下 { key=1; } return 0; } key.h #ifndef _key_H #define _key_H #include "system.h" #define KEY_LEFT_Pin GPIO_Pin_4 //定义K_LEFT管脚 #define KEY_DOWN_Pin GPIO_Pin_3 //定义K_DOWN管脚 #define KEY_RIGHT_Pin GPIO_Pin_2 //定义K_RIGHT管脚 #define KEY_UP_Pin GPIO_Pin_0 //定义KEY_UP管脚 #define KEY_Port (GPIOE) //定义端口 #define KEY_UP_Port (GPIOA) //定义端口 //使用位操作定义 #define K_UP PAin(0) #define K_DOWN PEin(3) #define K_LEFT PEin(4) #define K_RIGHT PEin(2) //使用读取管脚状态库函数定义 //#define K_UP GPIO_ReadInputDataBit(KEY_UP_Port,KEY_UP_Pin) //#define K_DOWN GPIO_ReadInputDataBit(KEY_Port,KEY_DOWN_Pin) //#define K_LEFT GPIO_ReadInputDataBit(KEY_Port,KEY_LEFT_Pin) //#define K_RIGHT GPIO_ReadInputDataBit(KEY_Port,KEY_RIGHT_Pin) //定义各个按键值 #define KEY_UP 1 #define KEY_DOWN 2 #define KEY_LEFT 3 #define KEY_RIGHT 4 void KEY_Init(void); u8 KEY_Scan(u8 mode); #endif ADC配置 adc.h #ifndef _adc_H #define _adc_H #include "system.h" void ADCx_Init(void); u16 Get_ADC_Value(u8 ch,u8 times); int Get_temp(void); #endif adc.c #include "adc.h" #include "SysTick.h" //初始化ADC void ADCx_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模拟输入模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//管脚设置 GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//浮空 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化结构体 //RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE); //ADC1复位 //RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE); //复位结束 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间的延迟5个时钟 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz ADC_CommonInit(&ADC_CommonInitStructure);//初始化 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换 ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐 ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化 ADC_Cmd(ADC1, ENABLE);//开启AD转换器 } //获取通道ch的转换值,取times次,然后平均 //ch:通道编号 //times:获取次数 //返回值:通道ch的times次转换结果平均值 u16 Get_ADC_Value(u8 ch,u8 times) { u32 temp_val=0; u8 t; //设置指定ADC的规则组通道,一个序列,采样时间 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_480Cycles); //ADC1,ADC通道,480个周期,提高采样时间可以提高精确度 for(t=0;t ADC_SoftwareStartConv(ADC1); //使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 temp_val+=ADC_GetConversionValue(ADC1); delay_ms(5); } return temp_val/times; } //得到温度值 //返回值:温度值(扩大了100倍,单位:℃.) int Get_temp(void) { u32 adc_value; int temp; double temperture; adc_value=Get_ADC_Value(ADC_Channel_5,20); //读取通道16内部温度传感器通道,10次取平均 temperture=(float)adc_value*(3.3/4096); //电压值 temperture=(temperture-0.38)/0.0025; //转换为温度值 + 25 temp=temperture*10; //扩大100倍. return temp; } 中断配置 定时器配置 #include "time.h" #include "led.h" #include "adc_temp.h" //per:重装载值 //psc:分频系数 extern u8 tempture_t; void TIM4_Init(u16 per,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能TIM4时钟 TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值 TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数 TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式 TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure); TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //开启定时器中断 TIM_ClearITPendingBit(TIM4,TIM_IT_Update); NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//定时器中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM4,ENABLE); //使能定时器 } 中断服务函数 void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4,TIM_IT_Update)) { led2=!led2; tempture.temp=Get_temp();//读ADC值 TIM4->ARR= tempture.Sampling_period-1;//读取周期可控制 } TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //标志位清零 } UI及主函数 #include "system.h" #include "SysTick.h" #include "led.h" #include "usart.h" #include "tftlcd.h" #include "key.h" #include "mpu6050.h" #include "inv_mpu.h" #include "inv_mpu_dmp_motion_driver.h" //#include "adc_temp.h" #include "adc.h" #include "time.h" u8 key;//按键 struct test { short temp; float temp_want; int mode; int Sampling_period; int u_limit; int l_limit; }; struct statue_menu { int temp_want; int temp_want_change; int Sampling_period; int Sampling_period_change; int key_switch; int u_limit; int l_limit; }; struct test tempture;//温度示数 struct statue_menu statue_menu_t;//显示示数 防止超限影响显示 //串口1发送1个字符 //c:要发送的字符 void usart1_send_char(u8 c) { while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); USART_SendData(USART1,c); } //传送数据给匿名四轴上位机软件(V2.6版本) //fun:功能字. 0XA0~0XAF //data:数据缓存区,最多28字节!! //len:data区有效数据个数 void usart1_niming_report(u8 fun,u8*data,u8 len) { u8 send_buf[32]; u8 i; if(len>28)return; //最多28字节数据 send_buf[len+3]=0; //校验数置零 send_buf[0]=0X88; //帧头 send_buf[1]=fun; //功能字 send_buf[2]=len; //数据长度 for(i=0;i for(i=0;i for(i=0;i } //发送加速度传感器数据和陀螺仪数据 //aacx,aacy,aacz:x,y,z三个方向上面的加速度值 //gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值 void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz) { u8 tbuf[12]; tbuf[0]=(aacx>>8)&0XFF; tbuf[1]=aacx&0XFF; tbuf[2]=(aacy>>8)&0XFF; tbuf[3]=aacy&0XFF; tbuf[4]=(aacz>>8)&0XFF; tbuf[5]=aacz&0XFF; tbuf[6]=(gyrox>>8)&0XFF; tbuf[7]=gyrox&0XFF; tbuf[8]=(gyroy>>8)&0XFF; tbuf[9]=gyroy&0XFF; tbuf[10]=(gyroz>>8)&0XFF; tbuf[11]=gyroz&0XFF; usart1_niming_report(0XA1,tbuf,12);//自定义帧,0XA1 } //通过串口1上报结算后的姿态数据给电脑 //aacx,aacy,aacz:x,y,z三个方向上面的加速度值 //gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值 //roll:横滚角.单位0.01度。 -18000 -> 18000 对应 -180.00 -> 180.00度 //pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 -> 90.00 度 //yaw:航向角.单位为0.1度 0 -> 3600 对应 0 -> 360.0度 void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw) { u8 tbuf[28]; u8 i; for(i=0;i<28;i++)tbuf=0;//清0 tbuf[0]=(aacx>>8)&0XFF; tbuf[1]=aacx&0XFF; tbuf[2]=(aacy>>8)&0XFF; tbuf[3]=aacy&0XFF; tbuf[4]=(aacz>>8)&0XFF; tbuf[5]=aacz&0XFF; tbuf[6]=(gyrox>>8)&0XFF; tbuf[7]=gyrox&0XFF; tbuf[8]=(gyroy>>8)&0XFF; tbuf[9]=gyroy&0XFF; tbuf[10]=(gyroz>>8)&0XFF; tbuf[11]=gyroz&0XFF; tbuf[18]=(roll>>8)&0XFF; tbuf[19]=roll&0XFF; tbuf[20]=(pitch>>8)&0XFF; tbuf[21]=pitch&0XFF; tbuf[22]=(yaw>>8)&0XFF; tbuf[23]=yaw&0XFF; usart1_niming_report(0XAF,tbuf,28);//飞控显示帧,0XAF } void menu_display() { if(key==KEY_UP) { statue_menu_t.key_switch--;//选项指示标志位 } if(key==KEY_DOWN) { statue_menu_t.key_switch++; } if(statue_menu_t.key_switch<0||statue_menu_t.key_switch>4)//超出范围清零 statue_menu_t.key_switch=0; if(statue_menu_t.key_switch==0) { LCD_ShowString(10+120,220,tftlcd_data.width,tftlcd_data.height,16,"<-"); LCD_ShowString(10+120,260,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,280,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,300,tftlcd_data.width,tftlcd_data.height,16," "); if(key==KEY_RIGHT) { statue_menu_t.temp_want=statue_menu_t.temp_want+1; } if(key==KEY_LEFT) { statue_menu_t.temp_want=statue_menu_t.temp_want-1; } } if(statue_menu_t.key_switch==1) { LCD_ShowString(10+120,220,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,260,tftlcd_data.width,tftlcd_data.height,16,"<-"); LCD_ShowString(10+120,280,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,300,tftlcd_data.width,tftlcd_data.height,16," "); if(key==KEY_RIGHT) { statue_menu_t.Sampling_period=statue_menu_t.Sampling_period+1000; } if(key==KEY_LEFT) { statue_menu_t.Sampling_period=statue_menu_t.Sampling_period-1000; } if(statue_menu_t.Sampling_period<500) {statue_menu_t.Sampling_period=500;} if(statue_menu_t.Sampling_period>=6000) {statue_menu_t.Sampling_period=6000;} } if(statue_menu_t.key_switch==2) { LCD_ShowString(10+120,220,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,260,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,280,tftlcd_data.width,tftlcd_data.height,16,"<-"); LCD_ShowString(10+120,300,tftlcd_data.width,tftlcd_data.height,16," "); if(key==KEY_RIGHT) { statue_menu_t.u_limit=statue_menu_t.u_limit+1; } if(key==KEY_LEFT) { statue_menu_t.u_limit=statue_menu_t.u_limit-1; } } if(statue_menu_t.key_switch==3) { LCD_ShowString(10+120,220,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,260,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,280,tftlcd_data.width,tftlcd_data.height,16," "); LCD_ShowString(10+120,300,tftlcd_data.width,tftlcd_data.height,16,"<-"); if(key==KEY_RIGHT) { statue_menu_t.l_limit=statue_menu_t.l_limit+1; } if(key==KEY_LEFT) { statue_menu_t.l_limit=statue_menu_t.l_limit-1; } } } int main() { u8 i=0; //u8 key; u8 report=1; short temp; //温度 u8 res; SysTick_Init(168); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组 // LED_Init();//LED灯初始化 USART1_Init(256000);//串口初始化 TFTLCD_Init(); //LCD初始化 KEY_Init(); //按键初始化 //ADC_Temp_Init(); ADCx_Init(); //ADC初始化 TIM4_Init(5000-1,8400-1); //定时500ms FRONT_COLOR=BLACK;//设置字体为黑色 LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"NJUST-ZJ STM32F4"); LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"170220228 LIU YIN FEI"); LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"TEMPTURE Test"); FRONT_COLOR=RED;//设置字体为红色 LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"TEMPTURE OK!"); //LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"K_UP:UPLOAD ON/OFF"); FRONT_COLOR=BLUE;//设置字体为蓝色 LCD_ShowString(10,170,tftlcd_data.width,tftlcd_data.height,16,"UPLOAD ON "); LCD_ShowString(10,200,tftlcd_data.width,tftlcd_data.height,16," Temp: . C"); LCD_ShowString(10,220,tftlcd_data.width,tftlcd_data.height,16," Want: . C"); LCD_ShowString(10,240,tftlcd_data.width,tftlcd_data.height,16," Mode: "); LCD_ShowString(10,260,tftlcd_data.width,tftlcd_data.height,16," period: ms"); LCD_ShowString(10,280,tftlcd_data.width,tftlcd_data.height,16," U_limit: C"); LCD_ShowString(10,300,tftlcd_data.width,tftlcd_data.height,16," L_limit: C"); /// //赋初值 tempture.temp_want=10.5;//期望温度赋值 statue_menu_t.temp_want=10.5; tempture.Sampling_period=5000;//采样周期ms statue_menu_t.Sampling_period=5000; tempture.u_limit=50; tempture.l_limit=0; statue_menu_t.u_limit=50; statue_menu_t.l_limit=0; while(1) { key=KEY_Scan(0);//单次按下有效//按键模式选择 menu_display(); //tempture.temp=Get_temp();//ADC读取温度 //显示参数处理 tempture.mode=0; //加热或者降温 //如果外界温度大于期望温度则降温 if(tempture.temp_want>tempture.temp) tempture.mode=0; else tempture.mode=1; //数据同步 tempture.u_limit=statue_menu_t.u_limit; tempture.l_limit=statue_menu_t.l_limit; tempture.temp_want=statue_menu_t.temp_want; tempture.Sampling_period=statue_menu_t.Sampling_period; tempture.temp_want=100*tempture.temp_want; //实时温度显示 if(tempture.temp<0) { LCD_ShowChar(10+48,200,'-',16,0); //显示负号 tempture.temp=-tempture.temp; } else LCD_ShowChar(10+48,200,' ',16,0); //去掉负号 LCD_ShowNum(10+48+8,200,tempture.temp/100,3,16); //显示整数部分 LCD_ShowNum(10+48+40,200,tempture.temp%10,1,16); //显示小数部分 //期望温度显示 LCD_ShowNum(10+48+8,220,tempture.temp_want/100,3,16); //显示整数部分 LCD_ShowNum(10+48+40,220,(int)tempture.temp_want/10,1,16); //显示小数部分 //模式显示 if(tempture.mode==0) LCD_ShowString(10,240,tftlcd_data.width,tftlcd_data.height,16," Mode:heating"); if(tempture.mode==1) LCD_ShowString(10,240,tftlcd_data.width,tftlcd_data.height,16," Mode:cooling"); //采样周期显示 LCD_ShowNum(10+48+14,260,tempture.Sampling_period,5,16); //显示整数部分 //上限显示 LCD_ShowNum(10+48+20,280,tempture.u_limit,3,16); //显示整数部分 //下限显示 LCD_ShowNum(10+48+20,300,tempture.l_limit,3,16); //显示整数部分 //按键操作测试 LCD_ShowNum(10,320,key,3,16); //显示整数部分 } } //中断服务函数 void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4,TIM_IT_Update)) { led2=!led2; tempture.temp=Get_temp();//读ADC值 TIM4->ARR= tempture.Sampling_period-1;//读取周期可控制 } TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //标志位清零 } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1683 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1582 浏览 1 评论
1013 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
703 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1627 浏览 2 评论
1892浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
675浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
538浏览 3评论
558浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
526浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-4 02:16 , Processed in 0.788663 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号