ֵ

u8 OLED_GRAM[128][8]; /************************************************************************** Function: Refresh the OLED screen Input : none Output : none گ˽٦ŜúˢтOLEDǁĻ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void OLED_Refresh_Gram(void) { u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //Set page address (0~7) //ʨ׃ҳַ֘è0~7é OLED_WR_Byte (0x00,OLED_CMD); //Set the display location - column low address //ʨ׃Дʾλ׃j֍ַ֘ OLED_WR_Byte (0x10,OLED_CMD); //Set the display location - column height address //ʨ׃Дʾλ׃jַٟ֘ for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA); } } void OLED_Refresh_Line(void) { u8 i,n; for(i=0;i<2;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //Set page address (0~7) //ʨ׃ҳַ֘è0~7é OLED_WR_Byte (0x00,OLED_CMD); //Set the display location - column low address //ʨ׃Дʾλ׃j֍ַ֘ OLED_WR_Byte (0x10,OLED_CMD); //Set the display location - column height address //ʨ׃Дʾλ׃jַٟ֘ for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA); } } /************************************************************************** Function: Refresh the OLED screen Input : Dat: data/command to write, CMD: data/command flag 0, represents the command;1, represents data Output : none گ˽٦ŜúвOLEDдɫһٶؖޚ ɫࠚӎ˽údat:Ҫдɫք˽ߝ/ļ®ìcmd:˽ߝ/ļ®Ҫ־ 0,ҭʾļ®;1,ҭʾ˽ߝ ׵ܘ ֵúϞ **************************************************************************/ void OLED_WR_Byte(u8 dat,u8 cmd) { u8 i; if(cmd) OLED_RS_Set(); else OLED_RS_Clr(); for(i=0;i<8;i++) { OLED_SCLK_Clr(); if(dat&0x80) OLED_SDIN_Set(); else OLED_SDIN_Clr(); OLED_SCLK_Set(); dat<<=1; } OLED_RS_Set(); } /************************************************************************** Function: Turn on the OLED display Input : none Output : none گ˽٦ŜúߪǴOLEDДʾ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void OLED_Display_On(void) { OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC command //SET DCDCļ® OLED_WR_Byte(0X14,OLED_CMD); //DCDC ON OLED_WR_Byte(0XAF,OLED_CMD); //DISPLAY ON } /************************************************************************** Function: Turn off the OLED display Input : none Output : none گ˽٦ŜúژҕOLEDДʾ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void OLED_Display_Off(void) { OLED_WR_Byte(0X8D,OLED_CMD); //SET DCDC command //SET DCDCļ® OLED_WR_Byte(0X10,OLED_CMD); //DCDC OFF OLED_WR_Byte(0XAE,OLED_CMD); //DISPLAY OFF } /************************************************************************** Function: Screen clear function, clear the screen, the entire screen is black, and did not light up the same Input : none Output : none گ˽٦Ŝúȥǁگ˽,ȥΪǁ,ֻٶǁώۚɫքìۍû֣һҹ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void OLED_Clear(void) { u8 i,n; for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00; OLED_Refresh_Gram(); //Update the display //ټтДʾ } /************************************************************************** Function: Draw point Input : x,y: starting coordinate;T :1, fill,0, empty Output : none گ˽٦Ŝúۭ֣ ɫࠚӎ˽úx,y :ǰ֣ظҪ; t:1,ͮԤ,0,ȥࠕ ׵ܘ ֵúϞ **************************************************************************/ void OLED_DrawPoint(u8 x,u8 y,u8 t) { u8 pos,bx,temp=0; if(x>127||y>63)return;//ӬԶ׶Χ‹. pos=7-y/8; bx=y%8; temp=1<<(7-bx); if(t)OLED_GRAM[x][pos]|=temp; else OLED_GRAM[x][pos]&=~temp; } /************************************************************************** Function: Displays a character, including partial characters, at the specified position Input : x,y: starting coordinate;Len: The number of digits;Size: font size;Mode :0, anti-white display,1, normal display Output : none گ˽٦Ŝú՚ָ֨λ׃Дʾһٶؖػ,Ѽ(ҿؖؖػ ɫࠚӎ˽úx,y :ǰ֣ظҪ; len :˽ؖքλ˽; size:ؖͥճС; mode:0,״їДʾ,1,ֽӣДʾ ׵ܘ ֵúϞ **************************************************************************/ void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode) { u8 temp,t,t1; u8 y0=y; chr=chr-' '; //Get the offset value //փսƫӆ۳քֵ for(t=0;t<size;t++) { if(size==12)temp=oled_asc2_1206[chr][t]; //Invoke 1206 font //ַԃ1206ؖͥ else temp=oled_asc2_1608[chr][t]; //Invoke the 1608 font //ַԃ1608ؖͥ for(t1=0;t1<8;t1++) { if(temp&0x80)OLED_DrawPoint(x,y,mode); else OLED_DrawPoint(x,y,!mode); temp<<=1; y++; if((y-y0)==size) { y=y0; x++; break; } } } } /************************************************************************** Function: Find m to the NTH power Input : m: base number, n: power number Output : none گ˽٦ŜúȳmքnՎ׽քگ˽ ɫࠚӎ˽úmú֗˽ìnúՎ׽˽ ׵ܘ ֵúϞ **************************************************************************/ u32 oled_pow(u8 m,u8 n) { u32 result=1; while(n--)result*=m; return result; } /************************************************************************** Function: Displays 2 numbers Input : x,y: starting coordinate;Len: The number of digits;Size: font size;Mode: mode, 0, fill mode, 1, overlay mode;Num: value (0 ~ 4294967295); Output : none گ˽٦ŜúДʾ2ٶ˽ؖ ɫࠚӎ˽úx,y :ǰ֣ظҪ; len :˽ؖքλ˽; size:ؖͥճС; mode:ģʽ, 0,ͮԤģʽ, 1,־ݓģʽ; num:˽ֵ(0~4294967295); ׵ܘ ֵúϞ **************************************************************************/ void OLED_ShowNumber(u8 x,u8 y,u32 num,u8 len,u8 size) { u8 t,temp; u8 enshow=0; for(t=0;t<len;t++) { temp=(num/oled_pow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { OLED_ShowChar(x+(size/2)*t,y,' ',size,1); continue; }else enshow=1; } OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); } } /************************************************************************** Function: Display string Input : x,y: starting coordinate;*p: starting address of the string Output : none گ˽٦ŜúДʾؖػԮ ɫࠚӎ˽úx,y :ǰ֣ظҪ; *p:ؖػԮǰʼַ֘ ׵ܘ ֵúϞ **************************************************************************/ void OLED_ShowString(u8 x,u8 y,const u8 *p) { #define MAX_CHAR_POSX 122 #define MAX_CHAR_POSY 58 while(*p!='\0') { if(x>MAX_CHAR_POSX){x=0;y+=16;} if(y>MAX_CHAR_POSY){y=x=0;OLED_Clear();} OLED_ShowChar(x,y,*p,12,1); x+=8; p++; } } void OLED_ShowString16(u8 x,u8 y,const u8 *p) { #define MAX_CHAR_POSX 122 #define MAX_CHAR_POSY 58 while(*p!='\0') { if(x>MAX_CHAR_POSX){x=0;y+=16;} if(y>MAX_CHAR_POSY){y=x=0;OLED_Clear();} OLED_ShowChar(x,y,*p,16,1); x+=8; p++; } } /************************************************************************** Function: Initialize the OLED Input : none Output : none گ˽٦ŜúԵʼۯOLED ɫࠚӎ˽: Ϟ ׵ܘ ֵúϞ **************************************************************************/ void OLED_Init(void) { // 1. 关闭显示 OLED_WR_Byte(0xAE, OLED_CMD); // 2. 硬件复位 OLED_RST_Clr(); delay_ms(10); OLED_RST_Set(); delay_ms(50); // 3. 重新配置GPIO GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOD, &GPIO_InitStructure); // 4. 精简初始化序列 const uint8_t init_seq[] = { 0xAE, // 关闭显示 0xD5, 0x80, // 时钟分频 0xA8, 0x3F, // 多路复用 0xD3, 0x00, // 显示偏移 0x40, // 起始行 0x8D, 0x14, // 开启充电泵 0x20, 0x02, // 页地址模式 0xA1, // 段重定向 0xC8, // COM扫描方向 0xDA, 0x12, // COM配置 0x81, 0xEF, // 对比度 0xD9, 0xF1, // 预充电 0xDB, 0x30, // VCOMH 0xA4, // 关闭全局显示 0xA6 // 正常显示模式 }; // 直接发送所有命令(无错误检查) for(uint8_t i=0; i<sizeof(init_seq); ) { OLED_WR_Byte(init_seq[i++], OLED_CMD); // 保留关键命令的固定延时结构(但移除条件判断) if(i==7 || i==9 || i==11) delay_ms(10); } // 5. 清屏并开启显示 OLED_Clear(); OLED_WR_Byte(0xAF, OLED_CMD); }#define SDA_IN() {GPIOB->MODER&=~(3<<(11*2));GPIOB->MODER|=0<<11*2;} //PB5ˤɫģʽ #define SDA_OUT() {GPIOB->MODER&=~(3<<(11*2));GPIOB->MODER|=1<<11*2;} //PB5ˤԶģʽ //IOәطگ˽ #define IIC_SCL PBout(10) //SCL #define IIC_SDA PBout(11) //SDA #define READ_SDA PBin(11) //ˤɫSDA #ifndef I2C_Direction_Transmitter #define I2C_Direction_Transmitter ((uint8_t)0x00) #endif #ifndef I2C_Direction_Receiver #define I2C_Direction_Receiver ((uint8_t)0x01) #endif enum { I2C_ACK, I2C_NACK };void I2C_GPIOInit(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//ʹŜGPIOBʱד GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//ǕͨˤԶģʽ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//ΆάˤԶ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ʏ- GPIO_Init(GPIOB, &GPIO_InitStructure);//Եʼۯ IIC_SCL=1; IIC_SDA=1; } /************************************************************************** Function: Simulate IIC start signal Input : none Output : none گ˽٦ŜúģŢIICǰʼхۅ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void I2C_Start(void) { SDA_OUT(); //sdaПˤԶ IIC_SDA=1; if(!READ_SDA)return ; IIC_SCL=1; delay_us(1); IIC_SDA=0;//START:when CLK is high,DATA change form high to low if(READ_SDA)return ; delay_us(1); IIC_SCL=0;//ǯסI2C؜Пì׼Ѹע̍ܲޓ˕˽ߝ return ; } /************************************************************************** Function: Analog IIC end signal Input : none Output : none گ˽٦ŜúģŢIICޡ˸хۅ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void I2C_Stop(void) { SDA_OUT();//sdaПˤԶ IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(1); IIC_SCL=1; IIC_SDA=1;//ע̍I2C؜Пޡ˸хۅ delay_us(1); } bool I2C_WaiteForAck(void) { u8 ucErrTime=0; SDA_IN(); //SDAʨ׃Ϊˤɫ IIC_SDA=1; delay_us(1); IIC_SCL=1; delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>50) { I2C_Stop(); return 0; } delay_us(1); } IIC_SCL=0;//ʱדˤԶ0 return 1; } /************************************************************************** Function: IIC response Input : none Output : none گ˽٦ŜúIICӦհ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void I2C_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(1); IIC_SCL=1; delay_us(1); IIC_SCL=0; } /************************************************************************** Function: IIC don't reply Input : none Output : none گ˽٦ŜúIICһӦհ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void I2C_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(1); IIC_SCL=1; delay_us(1); IIC_SCL=0; } bool I2C_WriteOneBit(uint8_t DevAddr, uint8_t RegAddr, uint8_t BitNum, uint8_t Data) { uint8_t Dat; Dat =I2C_ReadOneByte(DevAddr, RegAddr); Dat = (Data != 0) ? (Dat | (1 << BitNum)) : (Dat & ~(1 << BitNum)); I2C_WriteOneByte(DevAddr, RegAddr, Dat); return true; } bool I2C_WriteBits(uint8_t DevAddr, uint8_t RegAddr, uint8_t BitStart, uint8_t Length, uint8_t Data) { uint8_t Dat, Mask; Dat = I2C_ReadOneByte(DevAddr, RegAddr); Mask = (0xFF << (BitStart + 1)) | 0xFF >> ((8 - BitStart) + Length - 1); Data <<= (8 - Length); Data >>= (7 - BitStart); Dat &= Mask; Dat |= Data; I2C_WriteOneByte(DevAddr, RegAddr, Dat); return true; } /************************************************************************** Function: IIC sends a bit Input : none Output : none گ˽٦ŜúIICע̍һٶλ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ void I2C_WriteByte(uint8_t Data) { u8 t; SDA_OUT(); IIC_SCL=0;//-֍ʱדߪʼ˽ߝԫˤ for(t=0;t<8;t++) { IIC_SDA=(Data&0x80)>>7; Data<<=1; delay_us(1); IIC_SCL=1; delay_us(1); IIC_SCL=0; delay_us(1); } } u8 I2C_WriteOneByte(uint8_t DevAddr, uint8_t RegAddr, uint8_t Data) { I2C_Start(); I2C_WriteByte(DevAddr | I2C_Direction_Transmitter); I2C_WaiteForAck(); I2C_WriteByte(RegAddr); I2C_WaiteForAck(); I2C_WriteByte(Data); I2C_WaiteForAck(); I2C_Stop(); return 1; } bool I2C_WriteBuff(uint8_t DevAddr, uint8_t RegAddr, uint8_t Num, uint8_t *pBuff) { uint8_t i; if(0 == Num || NULL == pBuff) { return false; } I2C_Start(); I2C_WriteByte(DevAddr | I2C_Direction_Transmitter); I2C_WaiteForAck(); I2C_WriteByte(RegAddr); I2C_WaiteForAck(); for(i = 0; i < Num; i ++) { I2C_WriteByte(*(pBuff + i)); I2C_WaiteForAck(); } I2C_Stop(); return true; } /************************************************************************** Function: IIC reads a bit Input : none Output : none گ˽٦ŜúIICׁȡһٶλ ɫࠚӎ˽úϞ ׵ܘ ֵúϞ **************************************************************************/ uint8_t I2C_ReadByte(uint8_t Ack) { uint8_t i, RecDat = 0; SDA_IN(); for(i = 0; i < 8; i ++) { // I2C_SCL_Clr(); IIC_SCL=0; delay_us(1); // I2C_SCL_Set(); IIC_SCL=1; RecDat <<= 1; if(READ_SDA) RecDat |= 0x01; else RecDat &= ~0x01; delay_us(1); } if(I2C_ACK == Ack) I2C_Ack(); else I2C_NAck(); return RecDat; } uint8_t I2C_ReadOneByte(uint8_t DevAddr, uint8_t RegAddr) { uint8_t TempVal = 0; I2C_Start(); I2C_WriteByte(DevAddr | I2C_Direction_Transmitter); I2C_WaiteForAck(); I2C_WriteByte(RegAddr); I2C_WaiteForAck(); I2C_Start(); I2C_WriteByte(DevAddr | I2C_Direction_Receiver); I2C_WaiteForAck(); TempVal = I2C_ReadByte(I2C_NACK); I2C_Stop(); return TempVal; } bool I2C_ReadBuff(uint8_t DevAddr, uint8_t RegAddr, uint8_t Num, uint8_t *pBuff) { uint8_t i; if(0 == Num || NULL == pBuff) { return false; } I2C_Start(); I2C_WriteByte(DevAddr | I2C_Direction_Transmitter); I2C_WaiteForAck(); I2C_WriteByte(RegAddr); I2C_WaiteForAck(); I2C_Start(); I2C_WriteByte(DevAddr | I2C_Direction_Receiver); I2C_WaiteForAck(); for(i = 0; i < Num; i ++) { if((Num - 1) == i) { *(pBuff + i) = I2C_ReadByte(I2C_NACK); } else { *(pBuff + i) = I2C_ReadByte(I2C_ACK); } } I2C_Stop(); return true; }重写基于STM32F407的6针OLED 初始化
07-06
/* USER CODE BEGIN Header / /* @file : main.c @brief : Main program body @attention Copyright © 2025 STMicroelectronics. All rights reserved. This software is licensed under terms that can be found in the LICENSE file in the root directory of this software component. If no LICENSE file comes with this software, it is provided AS-IS. / / USER CODE END Header / / Includes ------------------------------------------------------------------*/ #include “main.h” #include “adc.h” #include “dma.h” #include “tim.h” #include “usart.h” #include “gpio.h” /* Private includes ----------------------------------------------------------/ / USER CODE BEGIN Includes */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include “arm_math.h” #include “arm_const_structs.h” #include “usart.h” /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------/ / USER CODE BEGIN PTD */ #define FFT_LENGTH 4096 #define MAX_HARMONIC_ORDER 5 #define FREQ_BINS_TO_SKIP 10 // 跳过低频噪声区域 #define switch_on HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET); #define switch_off HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET); #define FFT_LENGTH 4096 #define My_PI 3.14159265358979323846f // 新增:定义PI常量 __IO uint8_t AdcConvEnd = 0; uint16_t adcBuff[FFT_LENGTH]; uint8_t rxBuffer[4]={0}; uint8_t flag_30_40=0; uint8_t flag_30_100=0; uint8_t flag_300_40=0; uint8_t flag_300_100=0; uint8_t flag_30_1=0; uint8_t flag_300_1=0; float fft_inputbuf[FFT_LENGTH * 2]; float fft_outputbuf[FFT_LENGTH]; float hanningWindow[FFT_LENGTH]; // 新增:汉宁窗数组 float harmonicAmplitudes[MAX_HARMONIC_ORDER + 1] = {0}; // 存储各次谐波幅值 uint32_t harmonicIndices[MAX_HARMONIC_ORDER + 1] = {0}; // 存储各次谐波索引 uint32_t fundamentalIndex = 0; // 基波索引 float THD = 0.0f; // 总谐波失真度 /* USER CODE END PTD */ /* Private define ------------------------------------------------------------/ / USER CODE BEGIN PD */ //#define SAMPLING_FREQ 1846153.84615f //adc采样频率 (40k~100k) //#define SAMPLING_FREQ 1000000.0f//(9k~40k) float SAMPLING_FREQ=1000000.0f; /* USER CODE END PD */ /* Private macro -------------------------------------------------------------/ / USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ int fputc(int ch,FILE *f){ uint8_t temp[1] = {ch}; HAL_UART_Transmit(current_huart,temp,1,2); return ch; } //int fputc(int ch, FILE *f) //{ // HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff); // return ch; //} int fgetc(FILE *f) { uint8_t ch = 0; HAL_UART_Receive(&huart1, &ch, 1, 0xffff); return ch; } void HMI_WAVE(char* name,int ch,int val) { printf_2_wave(“add %s,%d,%d\xff\xff\xff”,name,ch,val); } void HMI_Wave_Clear(char* name,int ch) { printf_2_wave(“cle %s,%d\xff\xff\xff”,name,ch); } // 寻找基波频率位置 uint32_t findFundamentalFrequency(float* spectrum, uint32_t length) { float maxAmplitude = 0; uint32_t maxIndex = 0; // 跳过DC和低频噪声区域,寻找最大幅值作为基波 for (uint32_t i = FREQ_BINS_TO_SKIP; i < length / 2; i++) { if (spectrum[i] > maxAmplitude) { maxAmplitude = spectrum[i]; maxIndex = i; } } return maxIndex; } // 计算谐波失真度 void calculateHarmonicDistortion(float* spectrum, uint32_t fundamentalIdx, uint32_t fftLength) { // 存储基波信息 fundamentalIndex = fundamentalIdx; harmonicIndices[1] = fundamentalIdx; harmonicAmplitudes[1] = spectrum[fundamentalIdx]; float sumSquaredHarmonics = 0.0f; // 计算2~5次谐波 for (int order = 2; order <= MAX_HARMONIC_ORDER; order++) { uint32_t expectedIndex = fundamentalIdx * order; // 避免超出FFT范围 if (expectedIndex >= fftLength / 2) { harmonicIndices[order] = 0; harmonicAmplitudes[order] = 0.0f; continue; } // 在预期位置附近搜索最大值 int searchWindow = 3; float maxAmp = 0; uint32_t maxIdx = expectedIndex; for (int i = -searchWindow; i <= searchWindow; i++) { int idx = expectedIndex + i; if (idx >= 0 && idx < fftLength / 2 && spectrum[idx] > maxAmp) { maxAmp = spectrum[idx]; maxIdx = idx; } } harmonicIndices[order] = maxIdx; harmonicAmplitudes[order] = maxAmp; sumSquaredHarmonics += maxAmp * maxAmp; } // 计算总谐波失真度(THD) if (harmonicAmplitudes[1] > 0) { THD = 100.0f * sqrtf(sumSquaredHarmonics) / harmonicAmplitudes[1]; } else { THD = 0.0f; } } // 动态更新 void UpdateTimerParams_HAL(uint16_t newPSC, uint16_t newARR, float new_samplingfre) { // 停止定时器 HAL_TIM_Base_Stop(&htim3); // 使用HAL库宏设置参数 __HAL_TIM_SET_PRESCALER(&htim3, newPSC); __HAL_TIM_SET_AUTORELOAD(&htim3, newARR); SAMPLING_FREQ=new_samplingfre; // 重新启动定时器 HAL_TIM_Base_Start(&htim3); } /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------/ void SystemClock_Config(void); / USER CODE BEGIN PFP */ // 四舍五入函数 int round_double(double num) { return (int)(num + 0.5); } attribute((constructor)) void initHanningWindow() { for (int i = 0; i < FFT_LENGTH; i++) { hanningWindow[i] = 0.5f * (1.0f - cosf(2 * PI * i / (FFT_LENGTH - 1))); } } /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------/ / USER CODE BEGIN 0 */ /* 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_DMA_Init(); MX_ADC1_Init(); MX_TIM3_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); / USER CODE BEGIN 2 */ // ��������ʼ�� CFFT �ṹ��ʵ�� // arm_cfft_instance_f32 cfft_inst; HAL_UART_Receive_IT(&huart1,rxBuffer,4); //HAL_UART_Transmit_DMA(&huart2,(uint8_t )adcBuff,FFT_LENGTH); / USER CODE END 2 */ /* Infinite loop / / USER CODE BEGIN WHILE */ while (1) { if(flag_30_40) { switch_on; //继电器打开放大3倍 UpdateTimerParams_HAL(0,72-1,1000000); //动态改参数 选档 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH); HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd) //等待转换完成 ; // ================ 新增:加窗处理 ================ for (int i = 0; i < FFT_LENGTH; i++) { // 原始采样值乘以汉宁窗 float windowedValue = adcBuff[i] * hanningWindow[i]; fft_inputbuf[i * 2] = windowedValue * 3.3 / 4096; fft_inputbuf[i * 2 + 1] = 0; } // for (int i = 0; i < FFT_LENGTH; i++) // { // fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096; // fft_inputbuf[i * 2 + 1] = 0; // } arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1); arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); // fft_outputbuf[0] /= 4096; // for (int i = 1; i < FFT_LENGTH; i++)//�������г����ֵ // { // fft_outputbuf[i] /= 2048; // } // ================ 修改:优化归一化系数 ================ // 窗函数补偿系数 (汉宁窗为2.0) const float windowCompensation = 2.0f; fft_outputbuf[0] = fft_outputbuf[0] * windowCompensation / FFT_LENGTH; for (int i = 1; i < FFT_LENGTH; i++) { fft_outputbuf[i] = fft_outputbuf[i] * windowCompensation / (FFT_LENGTH / 2); } // 还原实际幅值(新增) for (int i = 0; i < FFT_LENGTH; i++) { fft_outputbuf[i] /= 3.0; // 除以放大倍数 然后再进行失真度分析 放大后和放大前的失真度应该是一样的 } // printf(“FFT Result:\r\n”); // for (int i = 0; i < 512; i++)//�������г����ֵ // { // printf(“%d:\t%.2f\r\n”, i, fft_outputbuf[i]); // } // 分析谐波 fundamentalIndex = findFundamentalFrequency(fft_outputbuf, FFT_LENGTH); calculateHarmonicDistortion(fft_outputbuf, fundamentalIndex, FFT_LENGTH); // printHarmonicAnalysisResults(); // 计算频率分辨率 float freqResolution = (float)SAMPLING_FREQ / FFT_LENGTH; printf_1_parameter(“t6.txt="%.2f"\xff\xff\xff”,harmonicIndices[1] * freqResolution);//基波频率 printf_1_parameter(“t8.txt="%.4f"\xff\xff\xff”,harmonicAmplitudes[1]); printf_1_parameter(“t2.txt="%.2f%%"\xff\xff\xff”,THD); //失真度 printf_2_wave(“%.2f”,harmonicIndices[1] * freqResolution); printf_2_wave(" %.4f",harmonicAmplitudes[1]); printf_2_wave(" %.2f%%",THD); // flag_30_40=0; HAL_UART_Receive_IT(&huart1,rxBuffer,4); } else if(flag_30_100) { switch_on; //放大 UpdateTimerParams_HAL(2,12,1846153.84615f); //动态改参数 选档 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH); HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd) //等待转换完成 ; // for (int i = 0; i < FFT_LENGTH; i++) // { // // fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096; // // fft_inputbuf[i * 2 + 1] = 0; // } // ================ 新增:加窗处理 ================ for (int i = 0; i < FFT_LENGTH; i++) { // 原始采样值乘以汉宁窗 float windowedValue = adcBuff[i] * hanningWindow[i]; fft_inputbuf[i * 2] = windowedValue * 3.3 / 4096; fft_inputbuf[i * 2 + 1] = 0; } arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1); arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); // ================ 修改:优化归一化系数 ================ // 窗函数补偿系数 (汉宁窗为2.0) const float windowCompensation = 2.0f; fft_outputbuf[0] = fft_outputbuf[0] * windowCompensation / FFT_LENGTH; for (int i = 1; i < FFT_LENGTH; i++) { fft_outputbuf[i] = fft_outputbuf[i] * windowCompensation / (FFT_LENGTH / 2); } // fft_outputbuf[0] /= 4096; // for (int i = 1; i < FFT_LENGTH; i++)//�������г����ֵ // { // fft_outputbuf[i] /= 2048; // } // 还原实际幅值(新增) for (int i = 0; i < FFT_LENGTH; i++) { fft_outputbuf[i] /= 3.0; // 除以放大倍数 } // printf(“FFT Result:\r\n”); // for (int i = 0; i < 512; i++)//�������г����ֵ // { // printf(“%d:\t%.2f\r\n”, i, fft_outputbuf[i]); // } // 分析谐波 fundamentalIndex = findFundamentalFrequency(fft_outputbuf, FFT_LENGTH); calculateHarmonicDistortion(fft_outputbuf, fundamentalIndex, FFT_LENGTH); // printHarmonicAnalysisResults(); // 计算频率分辨率 float freqResolution = (float)SAMPLING_FREQ / FFT_LENGTH; printf_1_parameter(“t6.txt="%.2f"\xff\xff\xff”,harmonicIndices[1] * freqResolution);//基波频率 printf_1_parameter(“t8.txt="%.4f"\xff\xff\xff”,harmonicAmplitudes[1]); printf_1_parameter(“t2.txt="%.2f%%"\xff\xff\xff”,THD); //失真度 // flag_30_100=0; printf_2_wave(“%.2f”,harmonicIndices[1] * freqResolution); printf_2_wave(" %.4f",harmonicAmplitudes[1]); printf_2_wave(" %.2f%%",THD); HAL_UART_Receive_IT(&huart1,rxBuffer,4); } else if(flag_300_40) { switch_off; //不需要放大 UpdateTimerParams_HAL(0,72-1,1000000); //动态改参数 选档 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH); // HAL_UART_Transmit_DMA(&huart2,(uint8_t *)adcBuff,FFT_LENGTH); HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd) //等待转换完成 ; // for (int i = 0; i < FFT_LENGTH; i++) // { // // fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096; // // fft_inputbuf[i * 2 + 1] = 0; // } // ================ 新增:加窗处理 ================ for (int i = 0; i < FFT_LENGTH; i++) { // 原始采样值乘以汉宁窗 float windowedValue = adcBuff[i] * hanningWindow[i]; fft_inputbuf[i * 2] = windowedValue * 3.3 / 4096; fft_inputbuf[i * 2 + 1] = 0; } arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1); arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); // ================ 修改:优化归一化系数 ================ // 窗函数补偿系数 (汉宁窗为2.0) const float windowCompensation = 2.0f; fft_outputbuf[0] = fft_outputbuf[0] * windowCompensation / FFT_LENGTH; for (int i = 1; i < FFT_LENGTH; i++) { fft_outputbuf[i] = fft_outputbuf[i] * windowCompensation / (FFT_LENGTH / 2); } // fft_outputbuf[0] /= 4096; // for (int i = 1; i < FFT_LENGTH; i++)//�������г����ֵ // { // fft_outputbuf[i] /= 2048; // } // printf(“FFT Result:\r\n”); // for (int i = 0; i < 512; i++)//�������г����ֵ // { // printf(“%d:\t%.2f\r\n”, i, fft_outputbuf[i]); // } // 分析谐波 fundamentalIndex = findFundamentalFrequency(fft_outputbuf, FFT_LENGTH); calculateHarmonicDistortion(fft_outputbuf, fundamentalIndex, FFT_LENGTH); // printHarmonicAnalysisResults(); // 计算频率分辨率 float freqResolution = (float)SAMPLING_FREQ / FFT_LENGTH; printf_1_parameter(“t6.txt="%.2f"\xff\xff\xff”,harmonicIndices[1] * freqResolution);//基波频率 printf_1_parameter(“t8.txt="%.4f"\xff\xff\xff”,harmonicAmplitudes[1]); printf_1_parameter(“t2.txt="%.2f%%"\xff\xff\xff”,THD); //失真度 // flag_300_40=0; printf_2_wave(“%.2f”,harmonicIndices[1] * freqResolution); printf_2_wave(" %.4f",harmonicAmplitudes[1]); printf_2_wave(" %.2f%%",THD); HAL_UART_Receive_IT(&huart1,rxBuffer,4); } else if(flag_300_100) { switch_off; //不需要放大 UpdateTimerParams_HAL(2,12,1846153.84615f); //动态改参数 选档 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH); HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd) //等待转换完成 ; // for (int i = 0; i < FFT_LENGTH; i++) // { // // fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096; // // fft_inputbuf[i * 2 + 1] = 0; // } // ================ 新增:加窗处理 ================ for (int i = 0; i < FFT_LENGTH; i++) { // 原始采样值乘以汉宁窗 float windowedValue = adcBuff[i] * hanningWindow[i]; fft_inputbuf[i * 2] = windowedValue * 3.3 / 4096; fft_inputbuf[i * 2 + 1] = 0; } arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1); arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); // ================ 修改:优化归一化系数 ================ // 窗函数补偿系数 (汉宁窗为2.0) const float windowCompensation = 2.0f; fft_outputbuf[0] = fft_outputbuf[0] * windowCompensation / FFT_LENGTH; for (int i = 1; i < FFT_LENGTH; i++) { fft_outputbuf[i] = fft_outputbuf[i] * windowCompensation / (FFT_LENGTH / 2); } // // printf(“FFT Result:\r\n”); // for (int i = 0; i < 512; i++)//�������г����ֵ // { // printf(“%d:\t%.2f\r\n”, i, fft_outputbuf[i]); // } // 分析谐波 fundamentalIndex = findFundamentalFrequency(fft_outputbuf, FFT_LENGTH); calculateHarmonicDistortion(fft_outputbuf, fundamentalIndex, FFT_LENGTH); // printHarmonicAnalysisResults(); // 计算频率分辨率 float freqResolution = (float)SAMPLING_FREQ / FFT_LENGTH; printf_1_parameter(“t6.txt="%.2f"\xff\xff\xff”,harmonicIndices[1] * freqResolution);//基波频率 printf_1_parameter(“t8.txt="%.4f"\xff\xff\xff”,harmonicAmplitudes[1]); printf_1_parameter(“t2.txt="%.2f%%"\xff\xff\xff”,THD); //失真度 // flag_300_100=0; printf_2_wave(“%.2f”,harmonicIndices[1] * freqResolution); printf_2_wave(" %.4f",harmonicAmplitudes[1]); printf_2_wave(" %.2f%%",THD); HAL_UART_Receive_IT(&huart1,rxBuffer,4); } else if(flag_30_1) { switch_on; //放大 UpdateTimerParams_HAL(0,720-1,100000); //动态改参数 选档 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH); HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd) //等待转换完成 ; // for (int i = 0; i < FFT_LENGTH; i++) // { // // fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096; // // fft_inputbuf[i * 2 + 1] = 0; // } // ================ 新增:加窗处理 ================ for (int i = 0; i < FFT_LENGTH; i++) { // 原始采样值乘以汉宁窗 float windowedValue = adcBuff[i] * hanningWindow[i]; fft_inputbuf[i * 2] = windowedValue * 3.3 / 4096; fft_inputbuf[i * 2 + 1] = 0; } arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1); arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); // ================ 修改:优化归一化系数 ================ // 窗函数补偿系数 (汉宁窗为2.0) const float windowCompensation = 2.0f; fft_outputbuf[0] = fft_outputbuf[0] * windowCompensation / FFT_LENGTH; for (int i = 1; i < FFT_LENGTH; i++) { fft_outputbuf[i] = fft_outputbuf[i] * windowCompensation / (FFT_LENGTH / 2); } // fft_outputbuf[0] /= 4096; // for (int i = 1; i < FFT_LENGTH; i++)//�������г����ֵ // { // fft_outputbuf[i] /= 2048; // } // 还原实际幅值(新增) for (int i = 0; i < FFT_LENGTH; i++) { fft_outputbuf[i] /= 3.0; // 除以放大倍数 } // printf(“FFT Result:\r\n”); // for (int i = 0; i < 512; i++)//�������г����ֵ // { // printf(“%d:\t%.2f\r\n”, i, fft_outputbuf[i]); // } // 分析谐波 fundamentalIndex = findFundamentalFrequency(fft_outputbuf, FFT_LENGTH); calculateHarmonicDistortion(fft_outputbuf, fundamentalIndex, FFT_LENGTH); // printHarmonicAnalysisResults(); // 计算频率分辨率 float freqResolution = (float)SAMPLING_FREQ / FFT_LENGTH; printf_1_parameter(“t6.txt="%.2f"\xff\xff\xff”,harmonicIndices[1] * freqResolution);//基波频率 printf_1_parameter(“t8.txt="%.4f"\xff\xff\xff”,harmonicAmplitudes[1]); printf_1_parameter(“t2.txt="%.2f%%"\xff\xff\xff”,THD); //失真度 // flag_30_100=0; printf_2_wave(“%.2f”,harmonicIndices[1] * freqResolution); printf_2_wave(" %.4f",harmonicAmplitudes[1]); printf_2_wave(" %.2f%%",THD); HAL_UART_Receive_IT(&huart1,rxBuffer,4); } else if(flag_300_1) { switch_off; //不需要放大 UpdateTimerParams_HAL(0,720-1,100000); //动态改参数 选档 HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH); HAL_TIM_Base_Start(&htim3); while (!AdcConvEnd) //等待转换完成 ; // for (int i = 0; i < FFT_LENGTH; i++) // { // // fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096; // // fft_inputbuf[i * 2 + 1] = 0; // } // ================ 新增:加窗处理 ================ for (int i = 0; i < FFT_LENGTH; i++) { // 原始采样值乘以汉宁窗 float windowedValue = adcBuff[i] * hanningWindow[i]; fft_inputbuf[i * 2] = windowedValue * 3.3 / 4096; fft_inputbuf[i * 2 + 1] = 0; } arm_cfft_f32(&arm_cfft_sR_f32_len4096, fft_inputbuf, 0, 1); arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); // ================ 修改:优化归一化系数 ================ // 窗函数补偿系数 (汉宁窗为2.0) const float windowCompensation = 2.0f; fft_outputbuf[0] = fft_outputbuf[0] * windowCompensation / FFT_LENGTH; for (int i = 1; i < FFT_LENGTH; i++) { fft_outputbuf[i] = fft_outputbuf[i] * windowCompensation / (FFT_LENGTH / 2); } // fft_outputbuf[0] /= 4096; // for (int i = 1; i < FFT_LENGTH; i++)//�������г����ֵ // { // fft_outputbuf[i] /= 2048; // } // printf(“FFT Result:\r\n”); // for (int i = 0; i < 512; i++)//�������г����ֵ // { // printf(“%d:\t%.2f\r\n”, i, fft_outputbuf[i]); // } // 分析谐波 fundamentalIndex = findFundamentalFrequency(fft_outputbuf, FFT_LENGTH); calculateHarmonicDistortion(fft_outputbuf, fundamentalIndex, FFT_LENGTH); // printHarmonicAnalysisResults(); // 计算频率分辨率 float freqResolution = (float)SAMPLING_FREQ / FFT_LENGTH; printf_1_parameter(“t6.txt="%.2f"\xff\xff\xff”,harmonicIndices[1] * freqResolution);//基波频率 printf_1_parameter(“t8.txt="%.4f"\xff\xff\xff”,harmonicAmplitudes[1]); printf_1_parameter(“t2.txt="%.2f%%"\xff\xff\xff”,THD); //失真度 // flag_300_100=0; printf_2_wave(“%.2f”,harmonicIndices[1] * freqResolution); printf_2_wave(" %.4f",harmonicAmplitudes[1]); printf_2_wave(" %.2f%%",THD); HAL_UART_Receive_IT(&huart1,rxBuffer,4); } /* 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 RCC Oscillators according to the specified parameters in the RCC_OscInitTypeDef structure. */ 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 = 4; RCC_OscInitStruct.PLL.PLLN = 144; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses 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_4) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // printf(“RX: 0x%02X\n”, rxBuffer[0]); // 添加调试输出 // printf(“RX: 0x%02X\n”, rxBuffer[1]); // printf(“RX: 0x%02X\n”, rxBuffer[2]); // printf(“RX: 0x%02X\n”, rxBuffer[3]); if(rxBuffer[0]==0xAA && rxBuffer[1]==0x02) { flag_30_100=0; flag_300_40=0; flag_300_100=0; flag_30_40=1; } else if(rxBuffer[0]==0xAA && rxBuffer[1]==0x03) { flag_30_40=0; flag_300_40=0; flag_300_100=0; flag_30_100=1; } else if(rxBuffer[0]==0xAA && rxBuffer[1]==0x05) { flag_30_40=0; flag_300_100=0; flag_30_100=0; flag_300_40=1; } else if(rxBuffer[0]==0xAA && rxBuffer[1]==0x06) { flag_300_40=0; flag_30_40=0; flag_30_100=0; flag_300_100=1; } else if(rxBuffer[0]==0xAA && rxBuffer[1]==0x01) { flag_300_40=0; flag_30_40=0; flag_30_100=0; flag_300_100=0; flag_300_1=0; flag_30_1=1; } else if(rxBuffer[0]==0xAA && rxBuffer[1]==0x04) { flag_300_40=0; flag_30_40=0; flag_30_100=0; flag_300_100=0; flag_30_1=0; flag_300_1=1; } // HAL_UART_Receive_IT(&huart2,rxBuffer,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 / __disable_irq(); while (1) { } / 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, ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) / / USER CODE END 6 / } #endif / USE_FULL_ASSERT */ 在这个基础上想用ADC实时监测波形并且用串口实时输出数据显示ADC测到的波形串口的显示波形函数只能 printf_2_wave(“add %s,%d,%d\xff\xff\xff”,name,ch,val);这个
最新发布
07-13
#include "gps.h" #include "sys.h" #include "string.h" #include "oled.h" #include "delay.h" #include "stdio.h" //Ԯࠚע̍ۺզȸ __align(8) uint8_t USART2_TX_BUF[USART_MAX_SEND_LEN]; //ע̍ۺԥ,خճUSART_MAX_SEND_LENؖޚ uint8_t USART2_RX_BUF[USART_MAX_RECV_LEN]; //ޓ˕ۺԥ,خճUSART_MAX_RECV_LENٶؖޚ. //Ԯࠚע̍һٶؖޚ static void Com_SendData(uint8_t data) { USART_SendData(USART2, data);//ע̍˽ߝ while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); } void HAL_UART_Transmit(USART_TypeDef* USARTx, uint8_t *pData, uint16_t Size) { uint16_t i; for(i=0;i<Size;i++) { Com_SendData(*(pData+i)); } } uint8_t NMEA_Comma_Pos(uint8_t *buf,uint8_t cx) { uint8_t *p=buf; while(cx) { if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//Զս'*'ܲ֟؇רؖػ,ղһզ՚֚cxٶֺۅ if(*buf==',')cx--; buf++; } return buf-p; } //m^nگ˽ //׵ܘֵ:m^nՎ׽. uint32_t NMEA_Pow(uint8_t m,uint8_t n) { uint32_t result=1; while(n--)result*=m; return result; } //strתۻΪ˽ؖ,Ӕ','ܲ֟'*'ޡ˸ //buf:˽ؖզԢȸ //dx:С˽֣λ˽,׵ܘٸַԃگ˽ //׵ܘֵ:תۻ۳ք˽ֵ int NMEA_Str2num(uint8_t *buf,uint8_t*dx) { uint8_t *p=buf; uint32_t ires=0,fres=0; uint8_t ilen=0,flen=0,i; uint8_t mask=0; int res; while(1) //փսֻ˽ۍС˽քӤ׈ { if(*p=='-'){mask|=0X02;p++;}//ˇغ˽ if(*p==','||(*p=='*'))break;//Զսޡ˸‹ if(*p=='.'){mask|=0X01;p++;}//ԶսС˽֣‹ else if(*p>'9'||(*p<'0')) //Ԑ؇רؖػ { ilen=0; flen=0; break; } if(mask&0X01)flen++; else ilen++; p++; } if(mask&0X02)buf++; //ȥִغۅ for(i=0;i<ilen;i++) //փսֻ˽ҿؖ˽ߝ { ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0'); } if(flen>5)flen=5; //خנȡ5λС˽ *dx=flen; //С˽֣λ˽ for(i=0;i<flen;i++) //փսС˽ҿؖ˽ߝ { fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0'); } res=ires*NMEA_Pow(10,flen)+fres; if(mask&0X02)res=-res; return res; } //ؖ϶GPGSVхϢ //gpsx:nmeaхϢޡٹͥ //buf:ޓ˕սքGPS˽ߝۺԥȸ˗ַ֘ void NMEA_GPGSV_Analysis(nmea_msg *gpsx,uint8_t *buf) { uint8_t *p,*p1,dx; uint8_t len,i,j,slx=0; uint8_t posx; p=buf; p1=(uint8_t*)strstr((const char *)p,"$GPGSV"); len=p1[7]-'0'; //փսGPGSVք͵˽ posx=NMEA_Comma_Pos(p1,3); //փսࠉݻπч؜˽ if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx); for(i=0;i<len;i++) { p1=(uint8_t*)strstr((const char *)p,"$GPGSV"); for(j=0;j<4;j++) { posx=NMEA_Comma_Pos(p1,4+j*4); if(posx!=0XFF)gpsx->slmsg[slx].num=NMEA_Str2num(p1+posx,&dx); //փսπчҠۅ else break; posx=NMEA_Comma_Pos(p1,5+j*4); if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//փսπчҶއ else break; posx=NMEA_Comma_Pos(p1,6+j*4); if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//փսπч׽λއ else break; posx=NMEA_Comma_Pos(p1,7+j*4); if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx); //փսπчхի҈ else break; slx++; } p=p1+1;//ȐۻսЂһٶGPGSVхϢ } } //ؖ϶GPGGAхϢ //gpsx:nmeaхϢޡٹͥ //buf:ޓ˕սքGPS˽ߝۺԥȸ˗ַ֘ void NMEA_GPGGA_Analysis(nmea_msg *gpsx,uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; p1=(uint8_t*)strstr((const char *)buf,"$GPGGA"); posx=NMEA_Comma_Pos(p1,6); //փսGPS״̬ if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx); posx=NMEA_Comma_Pos(p1,7); //փսԃԚ֨λքπч˽ if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx); posx=NMEA_Comma_Pos(p1,9); //փսڣюٟ׈ if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx); } //ؖ϶GPGSAхϢ //gpsx:nmeaхϢޡٹͥ //buf:ޓ˕սքGPS˽ߝۺԥȸ˗ַ֘ void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; uint8_t i; p1=(uint8_t*)strstr((const char *)buf,"$GPGSA"); posx=NMEA_Comma_Pos(p1,2); //փս֨λ`э if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx); for(i=0;i<12;i++) //փս֨λπчҠۅ { posx=NMEA_Comma_Pos(p1,3+i); if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx); else break; } posx=NMEA_Comma_Pos(p1,15); //փսPDOPλ׃ޫ׈Ӳؓ if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx); posx=NMEA_Comma_Pos(p1,16); //փսHDOPλ׃ޫ׈Ӳؓ if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx); posx=NMEA_Comma_Pos(p1,17); //փսVDOPλ׃ޫ׈Ӳؓ if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx); } //ؖ϶GPRMCхϢ //gpsx:nmeaхϢޡٹͥ //buf:ޓ˕սքGPS˽ߝۺԥȸ˗ַ֘ void NMEA_GPRMC_Analysis(nmea_msg *gpsx,uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; uint32_t temp; float rs; p1=(uint8_t*)strstr((const char *)buf,"GPRMC");//"$GPRMC",ޭӣԐ&ۍGPRMCؖߪքȩ࠶,ڊֻƐ׏GPRMC. posx=NMEA_Comma_Pos(p1,1); //փսUTCʱݤ if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx); //փսUTCʱݤ,ȥִms gpsx->utc.hour=temp/10000; gpsx->utc.min=(temp/100)%100; gpsx->utc.sec=temp%100; } posx=NMEA_Comma_Pos(p1,3); //փսγ׈ if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); gpsx->latitude=temp/NMEA_Pow(10,dx+2); //փս£ rs=temp%NMEA_Pow(10,dx+2); //փս' gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//תۻΪ£ } posx=NMEA_Comma_Pos(p1,4); //ŏγ۹ˇѱγ if(posx!=0XFF)gpsx->nshemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,5); //փսޭ׈ if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); gpsx->longitude=temp/NMEA_Pow(10,dx+2); //փս£ rs=temp%NMEA_Pow(10,dx+2); //փս' gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//תۻΪ£ } posx=NMEA_Comma_Pos(p1,6); //֫ޭ۹ˇϷޭ if(posx!=0XFF)gpsx->ewhemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,9); //փսUTCɕǚ if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); //փսUTCɕǚ gpsx->utc.date=temp/10000; gpsx->utc.month=(temp/100)%100; gpsx->utc.year=2000+temp%100; } } //ؖ϶GPVTGхϢ //gpsx:nmeaхϢޡٹͥ //buf:ޓ˕սքGPS˽ߝۺԥȸ˗ַ֘ void NMEA_GPVTG_Analysis(nmea_msg *gpsx,uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; p1=(uint8_t*)strstr((const char *)buf,"$GPVTG"); posx=NMEA_Comma_Pos(p1,7); //փս֘Ħ̙Ê if(posx!=0XFF) { gpsx->speed=NMEA_Str2num(p1+posx,&dx); if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx); //ȷѣ)ճ1000Ѷ } } //͡ȡNMEA-0183хϢ //gpsx:nmeaхϢޡٹͥ //buf:ޓ˕սքGPS˽ߝۺԥȸ˗ַ֘ void GPS_Analysis(nmea_msg *gpsx,uint8_t *buf) { NMEA_GPGSV_Analysis(gpsx,buf); //GPGSVޢ϶ NMEA_GPGGA_Analysis(gpsx,buf); //GPGGAޢ϶ NMEA_GPGSA_Analysis(gpsx,buf); //GPGSAޢ϶ NMEA_GPRMC_Analysis(gpsx,buf); //GPRMCޢ϶ NMEA_GPVTG_Analysis(gpsx,buf); //GPVTGޢ϶ } //GPSУҩۍ݆̣ //buf:˽ߝۺզȸ˗ַ֘ //len:˽ߝӤ׈ //cka,ckb:}ٶУҩޡڻ. void Ublox_CheckSum(uint8_t *buf,uint16_t len,uint8_t* cka,uint8_t*ckb) { uint16_t i; *cka=0;*ckb=0; for(i=0;i<len;i++) { *cka=*cka+buf[i]; *ckb=*ckb+*cka; } } extern uint16_t RX_len;//ޓ˕ؖޚ݆˽ extern void USART_BaudRate_Init(uint32_t Data); /////////////////////////////////////////UBLOX Ƥ׃պë///////////////////////////////////// //ݬөCFGƤ׃ִѐȩ࠶ //׵ܘֵ:0,ACKԉ٦ // 1,ޓ˕Ӭʱխϳ // 2,ûԐ֒սͬҽؖػ // 3,ޓ˕սNACKӦհ uint8_t Ublox_Cfg_Ack_Check(void) { uint16_t len=0,i; uint8_t rval=0; while(RX_len==0 && len<100)//ֈսޓ˕սӦհ { len++; delay_ms(5); } if(RX_len) { len=RX_len; for(i=0;i<len;i++)if(USART2_RX_BUF[i]==0XB5)break;//ө֒ͬҽؖػ 0XB5 if(i==len)rval=2; //ûԐ֒սͬҽؖػ else if(USART2_RX_BUF[i+3]==0X00)rval=3;//ޓ˕սNACKӦհ else rval=0; //ޓ˕սACKӦհ }else rval=1; return rval; } //Ƥ׃ѣզ //ݫձǰƤ׃ѣզ՚΢ҿEEPROMoĦ //׵ܘֵ:0,ִѐԉ٦;1,ִѐʧќ. uint8_t Ublox_Cfg_Cfg_Save(void) { uint8_t i; _ublox_cfg_cfg *cfg_cfg=(_ublox_cfg_cfg *)USART2_TX_BUF; cfg_cfg->header=0X62B5; //cfg header cfg_cfg->id=0X0906; //cfg cfg id cfg_cfg->dlength=13; //˽ߝȸӤ׈Ϊ13ٶؖޚ. cfg_cfg->clearmask=0; //ȥԽҚëΪ0 cfg_cfg->savemask=0XFFFF; //ѣզҚëΪ0XFFFF cfg_cfg->loadmask=0; //ݓ՘ҚëΪ0 cfg_cfg->devicemask=4; //ѣզ՚EEPROMoĦ Ublox_CheckSum((uint8_t*)(&cfg_cfg->id),sizeof(_ublox_cfg_cfg)-4,&cfg_cfg->cka,&cfg_cfg->ckb); HAL_UART_Transmit(USART2, (uint8_t *)&USART2_TX_BUF, sizeof(_ublox_cfg_cfg)); for(i=0;i<6;i++)if(Ublox_Cfg_Ack_Check()==0)break; //EEPROMдɫѨҪ҈ޏ߃ʱݤ,̹ӔlѸƐ׏נՎ return i==6?1:0; } //Ƥ׃NMEAˤԶхϢٱʽ //msgid:ҪәطքNMEAлϢ͵Ŀ,ߟͥݻЂĦքӎ˽ҭ // 00,GPGGA;01,GPGLL;02,GPGSA; // 03,GPGSV;04,GPRMC;05,GPVTG; // 06,GPGRS;07,GPGST;08,GPZDA; // 09,GPGBS;0A,GPDTM;0D,GPGNS; //uart1set:0,ˤԶژҕ;1,ˤԶߪǴ. //׵ܘֵ:0,ִѐԉ٦;Ǥ̻,ִѐʧќ. uint8_t Ublox_Cfg_Msg(uint8_t msgid,uint8_t uart1set) { _ublox_cfg_msg *cfg_msg=(_ublox_cfg_msg *)USART2_TX_BUF; cfg_msg->header=0X62B5; //cfg header cfg_msg->id=0X0106; //cfg msg id cfg_msg->dlength=8; //˽ߝȸӤ׈Ϊ8ٶؖޚ. cfg_msg->msgclass=0XF0; //NMEAлϢ cfg_msg->msgid=msgid; //ҪәطքNMEAлϢ͵Ŀ cfg_msg->iicset=1; //ĬɏߪǴ cfg_msg->uart1set=uart1set; //ߪژʨ׃ cfg_msg->uart2set=1; //ĬɏߪǴ cfg_msg->usbset=1; //ĬɏߪǴ cfg_msg->spiset=1; //ĬɏߪǴ cfg_msg->ncset=1; //ĬɏߪǴ Ublox_CheckSum((uint8_t*)(&cfg_msg->id),sizeof(_ublox_cfg_msg)-4,&cfg_msg->cka,&cfg_msg->ckb); HAL_UART_Transmit(USART2, (uint8_t *)&USART2_TX_BUF, sizeof(_ublox_cfg_msg)); return Ublox_Cfg_Ack_Check(); } //Ƥ׃NMEAˤԶхϢٱʽ //baudrate:Ҩ͘Ê,4800/9600/19200/38400/57600/115200/230400 //׵ܘֵ:0,ִѐԉ٦;Ǥ̻,ִѐʧќ(֢oһܡ׵ܘ0‹) uint8_t Ublox_Cfg_Prt(uint32_t baudrate) { _ublox_cfg_prt *cfg_prt=(_ublox_cfg_prt *)USART2_TX_BUF; cfg_prt->header=0X62B5; //cfg header cfg_prt->id=0X0006; //cfg prt id cfg_prt->dlength=20; //˽ߝȸӤ׈Ϊ20ٶؖޚ. cfg_prt->portid=1; //әطԮࠚ1 cfg_prt->reserved=0; //ѣ´ؖޚ,ʨ׃Ϊ0 cfg_prt->txready=0; //TX Readyʨ׃Ϊ0 cfg_prt->mode=0X08D0; //8λ,1ٶֹͣλ,ϞУҩλ cfg_prt->baudrate=baudrate; //Ҩ͘Êʨ׃ cfg_prt->inprotomask=0X0007;//0+1+2 cfg_prt->outprotomask=0X0007;//0+1+2 cfg_prt->reserved4=0; //ѣ´ؖޚ,ʨ׃Ϊ0 cfg_prt->reserved5=0; //ѣ´ؖޚ,ʨ׃Ϊ0 Ublox_CheckSum((uint8_t*)(&cfg_prt->id),sizeof(_ublox_cfg_prt)-4,&cfg_prt->cka,&cfg_prt->ckb); HAL_UART_Transmit(USART2, (uint8_t *)&USART2_TX_BUF, sizeof(_ublox_cfg_prt)); delay_ms(200); //ֈսע̍Ϊԉ USART_BaudRate_Init(baudrate); return Ublox_Cfg_Ack_Check();//֢oһܡ״ܘ0,ӲΪUBLOXעܘ4քӦհ՚ԮࠚטтԵʼۯքʱ۲ӑޭѻ֪Ǻ‹. } //Ƥ׃UBLOX NEO-6քʱדöԥˤԶ //interval:öԥݤٴ(us) //length:öԥ࠭׈(us) //status:öԥƤ׃:1,ٟ֧ƽԐЧ;0,ژҕ;-1,֍֧ƽԐЧ. //׵ܘֵ:0,ע̍ԉ٦;Ǥ̻,ע̍ʧќ. uint8_t Ublox_Cfg_Tp(uint32_t interval,uint32_t length,signed char status) { _ublox_cfg_tp *cfg_tp=(_ublox_cfg_tp *)USART2_TX_BUF; cfg_tp->header=0X62B5; //cfg header cfg_tp->id=0X0706; //cfg tp id cfg_tp->dlength=20; //˽ߝȸӤ׈Ϊ20ٶؖޚ. cfg_tp->interval=interval; //öԥݤٴ,us cfg_tp->length=length; //öԥ࠭׈,us cfg_tp->status=status; //ʱדöԥƤ׃ cfg_tp->timeref=0; //ӎ߼UTC ʱݤ cfg_tp->flags=0; //flagsΪ0 cfg_tp->reserved=0; //ѣ´λΪ0 cfg_tp->antdelay=820; //ͬПғʱΪ820ns cfg_tp->rfdelay=0; //RFғʱΪ0ns cfg_tp->userdelay=0; //ԃۧғʱΪ0ns Ublox_CheckSum((uint8_t*)(&cfg_tp->id),sizeof(_ublox_cfg_tp)-4,&cfg_tp->cka,&cfg_tp->ckb); HAL_UART_Transmit(USART2, (uint8_t *)&USART2_TX_BUF, sizeof(_ublox_cfg_tp)); return Ublox_Cfg_Ack_Check(); } //Ƥ׃UBLOX NEO-6քټт̙Ê //measrate:ӢʱݤݤٴìեλΪmsìخʙһŜСԚ200msè5Hzé //reftime:ӎ߼ʱݤì0=UTC Timeû1=GPS Timeèһѣʨ׃Ϊ1é //׵ܘֵ:0,ע̍ԉ٦;Ǥ̻,ע̍ʧќ. uint8_t Ublox_Cfg_Rate(uint16_t measrate,uint8_t reftime) { _ublox_cfg_rate *cfg_rate=(_ublox_cfg_rate *)USART2_TX_BUF; if(measrate<200)return 1; //СԚ200msìֱޓ΋Զ cfg_rate->header=0X62B5; //cfg header cfg_rate->id=0X0806; //cfg rate id cfg_rate->dlength=6; //˽ߝȸӤ׈Ϊ6ٶؖޚ. cfg_rate->measrate=measrate;//öԥݤٴ,us cfg_rate->navrate=1; //ռڽ̙Êèלǚéìڌ֨Ϊ1 cfg_rate->timeref=reftime; //ӎ߼ʱݤΪGPSʱݤ Ublox_CheckSum((uint8_t*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb); HAL_UART_Transmit(USART2, (uint8_t *)&USART2_TX_BUF, sizeof(_ublox_cfg_rate)); return Ublox_Cfg_Ack_Check(); } nmea_msg gpsx; __align(4) uint8_t dtbuf[50]; //Дʾۺԥ //ДʾGPS֨λхϢ void Gps_Msg_Show(void) { float tp; tp=gpsx.longitude; sprintf((char *)dtbuf,":%.5f %1c",tp/=100000,gpsx.ewhemi); //փսޭ׈ؖػԮ OLED_ShowCHinese(0,2,5);//ޭ OLED_ShowCHinese(16,2,7);//׈ OLED_ShowString(32,2,dtbuf); tp=gpsx.latitude; sprintf((char *)dtbuf,":%.5f %1c",tp/=100000,gpsx.nshemi); //փսγ׈ؖػԮ OLED_ShowCHinese(0,4,6);//γ OLED_ShowCHinese(16,4,7);//׈ OLED_ShowString(32,4,dtbuf); if(gpsx.fixmode<=3) //֨λ״̬ { gpsx.utc.hour = gpsx.utc.hour + 8; //ӑ֪քUTCʱݤìתۻԉѱީʱݤìӮ8Сʱ if(gpsx.utc.hour>=24) { gpsx.utc.hour-=24; } sprintf((char *)dtbuf,":%02d:%02d:%02d",gpsx.utc.hour,gpsx.utc.min,gpsx.utc.sec); //Дʾѱީʱݤ OLED_ShowCHinese(0,6,8);//ʱ OLED_ShowCHinese(16,6,9);//ݤ OLED_ShowString(32,6,dtbuf); } } void GpsDataRead(void) { uint16_t i,rxlen; if( RX_len) { rxlen=RX_len; for(i=0;i<rxlen;i++)USART2_TX_BUF[i]=USART2_RX_BUF[i]; USART2_TX_BUF[i]=0; //ؔ֯ͭݓޡ˸ػ GPS_Analysis(&gpsx,(uint8_t*)USART2_TX_BUF);//ؖ϶ؖػԮì˽ߝզɫGPSޡٹͥ Gps_Msg_Show(); //Дʾޭγ׈ìʱݤхϢ 请以以上32代码为参考编写基于海思hi3861外接NEO-6M-0-001的VScode代码需要.h文件.c文件template.c(主函数)文件,用的是uart2(io12-RX,io11-TX)在串口助手上显示出当前经纬度,并注释若想要与其他功能如倾斜传感器之类的连接需要修改哪些地方
07-06
f:\myopencv\myproject\app.py:130: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma? ('��ֵ������', self.threshold_debug, 'disabled') # ��ֵ�����԰�ť Traceback (most recent call last): File "f:\myopencv\myproject\app.py", line 249, in <module> a = app(window, 'ͼ��������') # ��ʼ��Ӧ�� ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "f:\myopencv\myproject\app.py", line 36, in __init__ self.tool_buttons = self.init_toolbar() ^^^^^^^^^^^^^^^^^^^ File "f:\myopencv\myproject\app.py", line 130, in init_toolbar ('��ֵ������', self.threshold_debug, 'disabled') # ��ֵ�����԰�ť ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: 'tuple' object is not callable [Done] exited with code=1 in 0.287 seconds [Running] python -u "f:\myopencv\myproject\app.py" f:\myopencv\myproject\app.py:130: SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma? ('��ֵ������', self.threshold_debug, 'disabled') # ��ֵ�����԰�ť Traceback (most recent call last): File "f:\myopencv\myproject\app.py", line 249, in <module> a = app(window, 'ͼ��������') # ��ʼ��Ӧ�� ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "f:\myopencv\myproject\app.py", line 36, in __init__ self.tool_buttons = self.init_toolbar() ^^^^^^^^^^^^^^^^^^^ File "f:\myopencv\myproject\app.py", line 130, in init_toolbar ('��ֵ������', self.threshold_debug, 'disabled') # ��ֵ�����԰�ť ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: 'tuple' object is not callable
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值