涉及频率捕获,多路pwm捕获,led扫描,按键扫描,ad采样,lcd液晶驱动,队列处理数据,排序输出。
工程链接
链接:https://pan.baidu.com/s/1YPu9g7w3-JNVrgv5iPo7qg
提取码:yzh1
主要代码参考
#include "work.h"
#include "stdbool.h"
#include "string.h"
#include "stdlib.h"
u8 LEDINDEX[] = { 0X00,1<<0,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7 };
u8 LEDDT[8] = {0};
u8 adct= 0;
u16 adcbuf[2];
u8 ledt = 0;
#define READB1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
#define READB2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
#define READB3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
#define READB4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
typedef struct key
{
u16 keytime;
u8 keystate;
bool sflag;
bool lflag;
bool state;
}key;
typedef struct mypuls{
u32 ts; //记录的脉冲值
u32 currentfreq; //测得频率
u8 flag; //开始信号/结束信号
u16 time; //记录的时间
} puls;
typedef struct mypwm{
u32 firstrisingcnt;
u32 secondrisingcnt;
u32 fallingcnt;
u32 validcnt; //有效计数值对应于脉宽
float freq;
float duty;
u16 updatetimes;
u8 state;
} pwms;
pwms mpwms[2] ={0};
puls m1 = {0};
key keys[4]={0};
bool uic = false; //数据 , 参数
bool mode = false ; // A -B
u8 pax = 20;
u8 pbx = 20;
u16 pf = 1000;
u32 freq =0;
u8 ax,bx; //角度变化量
float ag,bg; //角度
typedef struct mqueen
{
float buf[5];
u8 s;
}mqueen;
mqueen queen[2]= { 0 };
bool isflash = false; //是否刷新数据
u8 rxbuf[100];
u16 testtime = 0; //测试输出
void key_scan()
{
keys[0].state = READB1;
keys[1].state = READB2;
keys[2].state = READB3;
keys[3].state = READB4;
for(int i = 0 ; i < 4; i++)
{
switch(keys[i].keystate)
{
case 0:
if(!keys[i].state)keys[i].keystate = 1;
break;
case 1:
if(!keys[i].state)keys[i].keystate = 2;
else keys[i].keystate = 0;
break;
case 2:
if(!keys[i].state)
{
}
else{
keys[i].sflag = 1;
keys[i].keystate =0;
}
break;
}
}
}
void keyop(void)
{
if( keys[0].sflag )
{
uic =!uic;
keys[0].sflag =0 ;
}
else if(keys[1].sflag)
{
keys[1].sflag = 0;
if(!uic)return;
if(pax == 60) pax = 10;
else
pax +=10;
if(pbx == 60) pbx = 10;
else pbx += 10;
}
else if(keys[2].sflag)
{
keys[2].sflag = 0;
if(uic){
if(pf == 10000) pf =1000;
else pf+=1000;
}
else
{
mode = !mode;
}
}
else if(keys[3].sflag)
{
keys[3].sflag = 0;
if(!mode) isflash = true;
//数据刷新
}
}
//从小到大快速排序
void quick_sort(float * arr,int left,int right)
{
if(left >= right) return;
int i = left-1;
int j = right+1;
float mid = arr[(left+right) /2];
while(i < j)
{
do i++;while(arr[i] < mid);
do j--;while(arr[j] > mid);
if(i < j)
{
float temp =arr[i];
arr[i] =arr[j];
arr[j] = temp;
}
}
quick_sort(arr,left,j);
quick_sort(arr,j+1,right);
}
void flashdata(void)
{
//刷新数据
if(isflash)
{
int temp = ag;
if(mpwms[0].duty >= 90) ag= 180;
else
{
ag = 10+2.25f*mpwms[0].duty;
}
temp = ag-temp;
ax = abs(temp);
if(queen[0].s ==5)
{
u8 j =1;
while(j <= 4)
{
queen[0].buf[j-1] =queen[0].buf[j];
j++;
}
queen[0].buf[4] = ag; //越后越新
}
else //未装满
{
queen[0].buf[queen[0].s++] =ag;
}
temp = bg;
if(mpwms[1].duty >=90) bg = 180;
else
{
bg = 10+2.25f*mpwms[1].duty;
}
temp = bg-temp;
bx = abs(temp);
if(queen[1].s ==5)
{
u8 j =1;
while(j <= 4)
{
queen[1].buf[j-1] =queen[1].buf[j];
j++;
}
queen[1].buf[4] = bg; //越后越新
}
else //未装满
{
queen[1].buf[queen[1].s++] =bg;
}
freq = m1.currentfreq;
isflash =false;
}
}
void getadc()
{
if(!mode) return ;
static u16 oldval = 0;
if(adct > 50 )
{
adct = 0;
u16 newval = (adcbuf[0]+adcbuf[1])/2;
if(newval > 2000 && oldval < 2000) {
isflash =true;
}
oldval = newval ;
}
}
void led_display( u8 ds)
{
HAL_GPIO_WritePin(GPIOC,0XFF<<8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOC,ds<<8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void ledop(void)
{
if(ax > pax) LEDDT[0] =1;
else LEDDT[0] = 0;
if(bx > pbx) LEDDT[1] = 2;
else LEDDT[1] = 0;
if(freq > pf) LEDDT[2] =3;
else LEDDT[2] =0;
if(!mode) LEDDT[3] =4;
else LEDDT[3] =0;
if( abs((int)(90+bg-ag)) < 10 ) LEDDT[4] =5;
else LEDDT[4] = 0;
}
void myinit(void)
{
led_display(0);
}
void led_scan(void)
{
if(ledt > 50)
{
ledt = 0;
u8 temp = 0;
for(int i = 0 ; i < 8 ;i++)temp|=LEDINDEX[LEDDT[i]];
led_display(temp);
ledop();
}
}
void lcd_display(void)
{
//测试频率
// if(testtime > 1000)
// {
//
// printf("pwm1:%.2f - %.2f\r\n",mpwms[0].freq,mpwms[0].duty);
// printf("pwm2:%.2f - %.2f\r\n",mpwms[1].freq,mpwms[1].duty);
// testtime = 0;
// }
char temp[131];
if(!uic)
{
LCD_DisplayStringLine(Line1," DATA ");
sprintf(temp," a:%.1f ",ag);
LCD_DisplayStringLine(Line2,temp);
sprintf(temp," b:%.1f ",bg);
LCD_DisplayStringLine(Line3,temp);
sprintf(temp," f:%dHz ",freq);
LCD_DisplayStringLine(Line4,temp);
sprintf(temp," ax:%d ",ax);
LCD_DisplayStringLine(Line6,temp);
sprintf(temp," bx:%d ",bx);
LCD_DisplayStringLine(Line7,temp);
sprintf(temp," mode:%c ",!mode?'A':'B');
LCD_DisplayStringLine(Line8,temp);
}
else
{
LCD_DisplayStringLine(Line1," PARA ");
sprintf(temp," Pax:%d ",pax);
LCD_DisplayStringLine(Line2,temp);
sprintf(temp," Pbx:%d ",pbx);
LCD_DisplayStringLine(Line3,temp);
sprintf(temp," Pf:%d ",pf);
LCD_DisplayStringLine(Line4,temp);
LCD_DisplayStringLine(Line6," ");
LCD_DisplayStringLine(Line7," ");
LCD_DisplayStringLine(Line8," ");
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM6)
{
adct++;
ledt++;
testtime++;
if(m1.flag == 0) m1.flag = 1; //第一次进来
else if(m1.flag == 1){
if( ++m1.time == 1000) //测1s内
{
//已经测了1s
m1.time = 0;
m1.flag = 0;
m1.currentfreq = m1.ts;
m1.ts = 0;
}
}
}
else if(htim->Instance == TIM7)
{
key_scan();
}
else if(htim->Instance == TIM3)
{
//两路的更新计数值自加1,这里实际上可以用一个代替
mpwms[0].updatetimes++;
mpwms[1].updatetimes++;
}
}
void Inputcapturehandle(pwms * cpwm,u32 cnt,TIM_HandleTypeDef *htim,u32 ch)
{
u32 temp = 0;
switch(cpwm->state)
{
case 0: //测量上升沿
{
//开启下次为下降沿采样
__HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_FALLING);
//溢出计数值置为0
cpwm->updatetimes = 0;
//捕获第一次计数值
cpwm->firstrisingcnt =cnt;
//更新状态
cpwm->state = 1;
break;
}
case 1: //测量下降沿
{
//开启下一次为上升沿采样
__HAL_TIM_SET_CAPTUREPOLARITY(htim, ch, TIM_INPUTCHANNELPOLARITY_RISING);
//捕获下降沿的计数值
cpwm->fallingcnt = cnt;
//计算有效计数值(考虑溢出)
cpwm->validcnt = (cpwm->updatetimes * htim->Instance->ARR)+ cpwm->fallingcnt-cpwm->firstrisingcnt;
//溢出计数置为0
cpwm->updatetimes =0;
//更新下一状态
cpwm->state = 2;
break;
}
case 2: //再次测量上升沿
{
//捕获第二次上升沿的计数值
cpwm->secondrisingcnt = cnt;
//计算两个上升沿之间的计数值(考虑溢出)
temp = cpwm->secondrisingcnt + (cpwm->updatetimes * htim->Instance->ARR) - cpwm->firstrisingcnt;
//溢出计数值置为0
cpwm->updatetimes = 0;
//计算频率 = 定时器频率/一个PWM波的两个上升沿的计数值
cpwm->freq = 1e6/temp;
//计算占空比
cpwm->duty = cpwm->validcnt*1.0f / temp *100;
//更新状态
cpwm->state = 0;
}
break;
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
//计算脉冲个数
if(m1.flag == 1) m1.ts++;
}
}
else if(htim->Instance == TIM3)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
//进入到自己的中断回调函数中执行
Inputcapturehandle(&mpwms[0],TIM3->CCR1,htim,TIM_CHANNEL_1);
}
else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
//进入到自己的中断回调函数中执行
Inputcapturehandle(&mpwms[1],TIM3->CCR2,htim,TIM_CHANNEL_2);
}
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance ==USART1)
{
if(!strcmp(rxbuf,"a?"))
{
printf("a:%.1f\r\n",ag);
}
else if(!strcmp(rxbuf,"b?"))
{
printf("b:%.1f\r\n",bg);
}
else if(!strcmp(rxbuf,"aa?"))
{
u8 temp = queen[0].s;
if(temp){
printf("aa:");
temp -=1;
for(int k = 0 ; k < temp ; k++)
{
printf("%.1f-",queen[0].buf[k]);
}
printf("%.1f\r\n",queen[0].buf[temp]);
}
}
else if(!strcmp(rxbuf,"bb?"))
{
u8 temp = queen[1].s;
if(temp){
temp -=1;
printf("bb:");
for(int k = 0 ; k < temp ; k++)
{
printf("%.1f-",queen[1].buf[k]);
}
printf("%.1f\r\n",queen[1].buf[temp]);
}
}
else if(!strcmp(rxbuf,"qa?"))
{
printf("qa:");
float buf[6];
int len = queen[0].s;
for(int k = 0; k < len;k++) buf[k]=queen[0].buf[k];
quick_sort(buf,0,len-1);
for(int k = 0; k < len-1 ; k++)printf("%.1f-",buf[k]);
printf("%.1f\r\n",buf[len-1]);
}
else if(!strcmp(rxbuf,"qb?"))
{
printf("qb:");
float buf[6];
int len = queen[1].s;
for(int k = 0; k < len;k++) buf[k]=queen[1].buf[k];
quick_sort(buf,0,len-1);
for(int k = 0; k < len-1 ; k++)printf("%.1f-",buf[k]);
printf("%.1f\r\n",buf[len-1]);
}
else
{
printf("error\r\n");
}
memset(rxbuf,0x00,sizeof(rxbuf));
extern UART_HandleTypeDef huart1;
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rxbuf,100);
}
}