STM32G431-基础部分_stm32g431使用手册-程序员宅基地

技术标签: stm32  嵌入式硬件  单片机  

记性差,写下来方便看; 

本人主要学习配套视频是电子设计工坊的视频,觉得代码很精简,受益匪浅;

LED

编写代码
    //关闭所有灯
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, 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, led_value<<8, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

 若是需要对led以0.1s闪烁,可以以0.1s一次执行LED_Process(void);

在LED_Process中led进行异或操作,可以使得电平不断翻转;

KEY

配置流程

1.STM32CUBEMX:

配置按键连接引脚为GPIO_Input模式;

无需配置无上下拉模式;

PS:按键引脚已经上拉到高电平;

硬件电路图

IO口:未按下,高电平;按下,低电平;

编写代码

1.key编写;理解一下,多打几遍就记住了; 

#define KB1  HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define KB2  HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define KB3  HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define KB4  HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
#define KEYPORT  KB1 | (KB2<<1) | (KB3<<2) | (KB4<<3) | 0xf0

u8 Trg;          //单次触发
u8 Cont;       // 长按
void Key_Read(void)
{
    u8 ReadData = (KEYPORT)^0xff;//括号一定要有 ^的优先级很低
    Trg = ReadData & (ReadData ^ Cont);
    Cont = ReadData;
}

2.使用方法; 

__IO uint32_t KEYTick = 0;
void Key_Process(void)
{
	if(uwTick - KEYTick < 10) return ; 
	KEYTick = uwTick; 
	Key_Read();
    //短按
	if(Trg & 0x01)	//B1
	{
		do somethings...
	}
	if(Trg & 0x02)	//B2
	{
		do somethings...
	}
    //长按
    if(Cont & 0x01)	//B1
	{
		do somethings...
	}

}

ADC

配置流程

1.STM32CUBEMX:

设置ADC的GPIO为ADC输入模式;

设置成单端模式(Single-edned);

特别注意:在时钟树界面查看,ADC的时钟是否打开,为80M;

2.从模板中移植adc.c和adc.h代码到编程工程;(移植流程非常固定)

2.1在main函数当中添加adc.h,并添加ADC初始化代码;

2.2配置stm32g4xx_hal_conf.h文件,取消注释#define HAL_ADC_MODULE_ENABLE);

2.3开启ADC的外设时钟,并添加结构体定义;

2.4添加ADC相关的HAL库驱动文件(stm32gxx_hal_adc.c和stm32gxx_hal_adc_ex;

3.调用函数:

(1)HAL_ADC_Start:启动ADC转换;

(2)HAL_ADC_GetValue:读取ADC采集的值;

PS:测量一次ADC就要启动一起ADC;

硬件电路图

 编写代码
HAL_ADC_Start(&hadc1);
ADC1_Val = HAL_ADC_GetValue(&hadc1);
ADC1_R38_Voltage = ADC1_Val / 4096.0f * 3.3f;

有些题目需要对adc采集到的数据进行滤波处理;

进行均值滤波,采集10个数据求平均即可; 

AT24C02(EEPROM)

配置流程

1.移植资源数据包里的i2c.hi2c.c文件;初始化I2CInit();

2.在i2c.c文件当中编写AT24C02读写函数;并声明函数;

3.测试读写函数;

编写代码

1.AT24C02的读写函数;

AT24C02的设备地址是0xA0;

特别注意:写操作之后需要延时一段时间,给芯片写的时间;

//写24C02
void EEPROM_Write(u8 add,u8 dat)
{
	I2CStart(); 
	I2CSendByte(0xa0); 
	I2CWaitAck(); 
	
	I2CSendByte(add);	
	I2CWaitAck(); 
	I2CSendByte(dat); 
	I2CWaitAck(); 
	I2CStop();
	HAL_Delay(5); //延时5ms
}
//读24C02
u8 EEPROM_Read(u8 add)
{
	u8 dat;
	
	I2CStart(); 
	I2CSendByte(0xa0);
	I2CWaitAck(); 	
	I2CSendByte(add);
	I2CWaitAck(); 
	
	I2CStart();
	I2CSendByte(0xa1); 
	I2CWaitAck();
	dat = I2CReceiveByte(); 
	I2CSendNotAck();
	I2CStop();
	
	return(dat);
}

 以下函数可实现板子复位次数,在main函数中进行初始化,不需要再while中一直执行;

void EEPROM_Init(void)
{
	if(EEPROM_Read(0x22) == 0x78)	//不是第一次开机,open_num++
	{
		open_num = EEPROM_Read(0x00);	//上电读取open_num的值
		open_num++;
		EEPROM_Write(0x00, open_num);
	}
	if(EEPROM_Read(0x22) != 0x78)	//是第一次开机,open_num写为1
	{
		EEPROM_Write(0x22, 0x78);
		EEPROM_Write(0x00, 1);
		open_num = EEPROM_Read(0x00);	//上电读取open_num的值
	}
}

MCP4017

1. STM32CUBEMX:

设置ADC的GPIO为ADC输入模式;

并设置成单端模式(Single-edned);

2.设置ADC的转换通道数目(Numbei Of Conversion)大于1时;要设置Rank和Sample Time;

3.将新生成的代码移植到工程文档;

4.在i2c.c文件当中编写MCP4017读写函数;并声明函数;测试完成读写程序;

5.调用函数:

(1)HAL_ADC_Start:启动ADC转换;

(2)HAL_ADC_GetValue:读取ADC采集的值;

 硬件电路图

 编写代码

1.MCP4017的读写函数;

MCP4017的设备地址是0x5E;

void MCP4017_Write(u8 Val)
{
	I2CStart();
	I2CSendByte(0x5E);
	I2CWaitAck();
	
	I2CSendByte(Val);
	I2CWaitAck();
	I2CStop();
}

//读MCP4017
u8 MCP4017_Read(void)
{
	u8 val; 
	I2CStart();
	I2CSendByte(0x5F);  
	I2CWaitAck();
	
	val = I2CReceiveByte();
	I2CSendNotAck();
	I2CStop();

	return val;
}

 以下代码adc1转换有两个通道,adc2转换有一个通道;

//adc1
u16 adc1_r38_value;
u16 adc1_mcp_value;
u8 mcp_data;
float adc1_r38_vol;
float adc1_mcp_vol;
//adc2
u16 adc2_r37_value;
float adc2_r37_vol;
void ADC_Process(void)
{
	MCP4017_Write(0x6f);				//写数据	
	mcp_data = MCP4017_Read();	//读数据验证
	//获取adc1通道5的电压值 通道5排序第1
	HAL_ADC_Start(&hadc1);
	adc1_mcp_value = HAL_ADC_GetValue(&hadc1);
	adc1_mcp_vol = adc1_mcp_value / 4096.0f * 3.3f;
	//获取adc1通道11的电压值 通道11排序第2
	HAL_ADC_Start(&hadc1);
	adc1_r38_value = HAL_ADC_GetValue(&hadc1);
	adc1_r38_vol = adc1_r38_value / 4096.0f * 3.3f;
	//获取adc2通道15的电压值
	HAL_ADC_Start(&hadc2);
	adc2_r37_value = HAL_ADC_GetValue(&hadc2);
	adc2_r37_vol = adc2_r37_value / 4096.0f * 3.3f;
}

 LCD

注意事项

1.LCD分辨率320*240;最多显示十行,

从Line0~Line9;每行最多显示20个字符;

2.sprintf函数:需包含头文件“stdio.h>”;

注意避免长数据对短数据的覆盖;

3.使用赛场资源历程HAL_06_LCD可以不用再配置LED的引脚,可直接使用;

但是需要配置PD2为输出模式;低电平保持,高电平可修改;

硬件电路图

编写代码

1.sprintf函数的基本使用方法;定义char display_buf[20]数据存放数组;

DAC

配置流程

1.STM32CUBEMX:

配置DAC输的GPIO为DAC输出通道

模式为输出到外部引脚(Connected to external pin only);

PA4-DAC1_CH1  PA5-DAC1_CH2;

2.将新生成的代码移植到工程文档;无需开启外设时钟;

3.调用函数:

(1)HAL_DAC_SetValue:设置DAC转换的值;

(2)HAL_DAC_Start:启动DAC转换;

DAC资源查询

 <<数据手册>>4.4.10

硬件电路图

编写代码
DAC_CH1_Voltage = (1.1f/3.3f)*4095;
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DAC_CH1_Voltage);
HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);

 RTC

配置流程

1.STM32CUBEMX:

激活RTC的时钟和日历功能;(打两个勾即可)

2.配置RTC的时钟,初始化状态,将RTC模块的时钟配置成1Hz,对应1s;

3.RTC采用内部低速时钟(LIS);即32KHz,默认就是,不需要修改;

4.将rtc.c和rtc.h移植到工程文档;开启外设时钟;

5.调用函数:

(1)HAL_RTC_GetTime:获取时间;

(2)HAI_RTC_GetData:获取日期;

实现功能

1.获取年月日和时分秒毫秒;可分闰年大月小月;

2,注意编码格式是BCD编码;调试和LCD显示时用十六进制%x进行显示;

编写代码
RTC_TimeTypeDef sTime;//时间结构体
RTC_DateTypeDef sDate;//日期结构体
void RTC_Process(void)
{
	HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BCD);	//获取时间
	HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BCD);	//获取日期
//显示日期
sprintf((char *)display_buf, "%02x-%02x-%02x", sDate.Year, sDate.Month, sDate.Date);	            
LCD_DisplayStringLine(Line2, display_buf);
//显示时间
sprintf((char *)display_buf, "%02x-%02x-%02x", sTime.Hours,sTime.Minutes,sTime.Seconds);	
LCD_DisplayStringLine(Line3, display_buf);

}

USART-TX

配置流程

1.STM32CUBEMX:

配置USART1的PA9和PA10为串口收发引脚;

USART的Mode选择Asynchronous;

2.根据需求,配置USART的波特率,数据位长度,奇偶校验位,停止位和时钟;

3.将uart.c和uart.h移植到工程文档;开启外设时钟;

4.调用函数:

(1)HAL_UART_Transmit:串口发送函数;

硬件电路图

硬件连接已确定,只能使用PA9和PA10;

编写代码

1.在usart.c当中编写fputc函数;

int fputc(int ch, FILE *f) 
{
  /* Your implementation of fputc(). */
  HAL_UART_Transmit(&huart1, (unsigned char *)&ch, 1, 50);
  return ch;
}

 可以在菜单栏的Help的uVision help查找fputc;

里面有大部分的代码,修改成上方那样即可;

 2.在main函数中调用printf可输出字符和变化的数据; 用STC-ISP进行接收数据

PS:字符的长度需要-1,因为包含了结束符;

u8 USART_Arr[]={"你好\r\n"};//无需定义数组的大小 否则产生结束符影响下一次串口发送
void USART_Process(void)
{
HAL_UART_Transmit(&huart1,(unsigned char*)"HelloWorld\r\n",sizeof("HelloWorld\r\n")-1,50);	//有结束符
HAL_UART_Transmit(&huart1,(unsigned char *)USART_Arr,sizeof(USART_Arr)-1,50);
	
printf("D = %d \r\n", 123);	//无结束符
printf("F = %f \r\n", 123.123);
printf("HelloWorld \r\n");
}

USART-RX 

配置流程

1.勾选NVIC Setting中的使能USART1的中断;

2.初始化里,开启中断HAL_UART_Receive_IT(&huart1,usart_buf,1);

3.main.c文件当中重定义接收回调函数void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);

4.在回调函数中打断点,硬件仿真用STC_ISP发送数据测试能不能进入中断里面;

5.编写接收回调函数,函数需要调用HAL_UART_Receive_IT(&huart1,usart_buf,1);

编写代码

1.定义一个两位数组,用于中断接收收到的数据;

2.再定义一个多位数组,存放每次两位数组接收到的数据;

3.使用 if 函数对换行符进行判断,判断接收到的数据是否结束;换行符为‘\n’ ;0a 0d

4.发送数据时,需要在数据结尾带上0a 0d;

5.编写串口清除函数RxIdle_Process();

函数功能:对存放数据的数组进行清除,防止数据的堆叠;保证每次接收到的数据从第一位开始;

6.可以将接收到数据进行处理,但是要避免出现0a 0d这两个数据处理外设;

u8 usart_buf[2];    //中断接收数组
u8 rx_buf[10];    //数据存放数组
u8 rx_cnt = 0;    //存放数组位
u8 rx_flag_lcd = 0;
__IO uint32_t USARTTick = 0;
//串口接收
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//do somethings
	USARTTick = uwTick;			//更新计时
	rx_buf[rx_cnt] = usart_buf[0];	//存放接收字符
	rx_cnt++;
	if(usart_buf[0] == '\n')//换行符 0a 0d
	{
		rx_cnt = 0;
		if( (rx_buf[1] == 0x0a) || (rx_buf[1] == 0x0d))//避免换行符提前出现,若是多个位置如何避免
		{
			rx_buf[1] = 0x00;
		}
		LED_Disp(rx_buf[1]);		
		rx_flag_lcd = 1;
	}
	HAL_UART_Receive_IT(&huart1, usart_buf, 1);//开启下一次串口中断
}

//串口接收清除
void RxIdle_Process(void)
{
	u8 i;

	if(uwTick - USARTTick < 50) return ; //50ms到?
	USARTTick = uwTick;
 

	rx_cnt = 0;//清除数组内容
	rx_flag_lcd = 0;
	memset(rx_buf, '\0', sizeof(rx_buf));//数组清除函数,需要包含头文件"string.h"头文件
}

PWM测量输入信号

配置流程

1.STM32CUBEMX:

开启TIM的GPIO的定时器功能;

通道模式配制成输入捕获模式(Input Capture direct mode);打开NVIC;

配置预分频值PSC为80,每1us自增1;根据需求配置ARR的值;

配置ARR为0xFFFF(65535);对应测量取值范围为15H-1MHZ;

配置ARR为0xFFFF_FFFF(2^32);对应测量取值范围为0.00023H-1MHZ;

2.将tim.c和tim.h的代码移植到工程文档;

3.开始定时器PWM捕获中断HAL_TIM_IC_Start_IT(&htimx,TIM_CHANNEL_y)

4.编写回调函数;

5.在回调函数当中设置断点,能不能进入中断当中

6.编写PWM回调函数,再次调用HAL_TIM_IC_Start_IT(&htimx,TIM_CHANNEL_y)

7.调用函数:

(1)__HAL_TIM_SetCounter:设置计数器的值;一般用来清零;

(2)__HAL_TIM_GetCounter:获取计数器的值;获取占空比和周期;

(3)TIM2->CCER:修改上升或者下降沿触发中断;

最后在回调函数中进行数据处理得到测量信号的频率和占空比;

硬件电路图

编写代码

1.回调函数中获取测量信号的频率和占空比; 

u32 pwm_tim3_cnt1;
u32 pwm_tim3_cnt2;
u8 pwm_tim3_state;
u32 pwm_tim3_freq;
float pwm_tim3_duty;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    //如果是多个通道输入捕获,则进行if判断
	if(htim == &htim3)
	{
		if(pwm_tim3_state == 0)
		{
			__HAL_TIM_SetCounter(&htim3, 0);	//开始计时
			TIM3->CCER |= 0x0002;	//转为下降沿触发中断
			pwm_tim3_state = 1;
		}
		else if(pwm_tim3_state == 1)
		{
			pwm_tim3_cnt1 = __HAL_TIM_GetCounter(&htim3);	//获取占空比时间
			TIM3->CCER &= ~0x0002;	//转为上升沿触发中断
			pwm_tim3_state = 2;
		}
		else if(pwm_tim3_state == 2)
		{
			pwm_tim3_cnt2 = __HAL_TIM_GetCounter(&htim3);	//获取周期时间
			pwm_tim3_freq = 1000000 / pwm_tim3_cnt2;
			pwm_tim3_duty = pwm_tim3_cnt1 * 100.0f / pwm_tim3_cnt2;
			pwm_tim3_state = 0;
		}
		HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
	}
}

 CCER进行修改的值根据不同的定时器通道的值也不同,根据参考手册查看

PWM输出方波信号

配置流程

1.STM32CUBEMX:

开启TIM的GPIO的定时器功能;

通道模式为PWM产生通道(PWM Generation CH1);

配置预分频值PSC为80,每1us自增1;

根据需求配置ARR的值和Pluse的值;

PWM模式选mode1;极性选择高;

以上都根据需要而定,可以组合成不同频率和占空比的信号;

2..将tim.c和tim.h的代码移植到工程文档;

3..调用函数:

(1)HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_y):启动指定定时器通道生成PWM;

(2)TIM16->ARR = 499:修改输出信号频率;

(3)TIM17->CCRx = 500:修改指定通道输出信号的占空比;注意写上通道值;

硬件电路图

编写代码

其他

一、按键长按:
//KB4长按
if(Cont & 0x08)	//按键长按
{
	kb4_cnt++;	//长按计时
}
if((Trg == 0x00) && (Cont == 0x00))    //无按键按下
{
	if(kb4_cnt >= 65)	    //2s到?
	{
		kb4_cnt = 0;	    //清零
		do somethings...
	}
	else if (kb4_cnt != 0)	//2s未到
	{
		kb4_cnt = 0;	    //清零,防止累加
	}
}
//按键程序每31ms执行一次;所以200/31=65;当长按计次到65时代表大约2s到了
二、细节

1.工程需包含#include “stdio.h”和 #include “string.h” ,#include “lcd.h” ;方便之后编写代码;

2.STM32CUBEMX新生成的工程,下载设置中添加128k的芯片类型;

3.串口接收到的数据为ASCII码,转换为普通的数据需要进行        -‘\0’处理;

4.结构体定义的方法

typedef struct
{
	u8 tyep[5];
	u8 code[5];
	u8 in_year;
	u8 in_month;
	u8 in_day;
	u8 in_hour;
	u8 in_minute;
	u8 in_second;
	u8 pos;	//停车位置 1-8
} TYPE_CAR_INFO;
TYPE_CAR_INFO car_infomation[8];

                       

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_69076249/article/details/136410896

智能推荐

适合入门的8个趣味机器学习项目-程序员宅基地

文章浏览阅读86次。首发地址:https://yq.aliyun.com/articles/221708谈到机器学习,相信很多除学者都是通过斯坦福大学吴恩达老师的公开课《Machine Learning》开始具体的接触机器学习这个领域,但是学完之后又不知道自己的掌握情况,缺少一些实际的项目操作。对于机器学习的相关竞赛挑战,有些项目的门槛有些高,参加后难以具体的实现,因此造..._scrath五子棋下载

oracle 12c avg,Oracle 12c新特性系列专题-安徽Oracle授权认证中心-程序员宅基地

文章浏览阅读83次。原标题:Oracle 12c新特性系列专题-安徽Oracle授权认证中心 随着Oracle database 12c的普及,数据库管理员 (DBA) 的角色也随之发生了转变。 Oracle 12c数据库对 DBA 而言是下一代数据管理。它让 DBA 可以摆脱单调的日常管理任务,能够专注于如何从数据中获取更多价值。未来我们会推出基于Oracle12c的技术文章,帮助DBA尽快掌握新一代数据库的新特性..._ilm add policy row store compress advanced row after

第七周项目三(负数把正数赶出队列)-程序员宅基地

文章浏览阅读150次。问题及代码:*Copyright(c)2016,烟台大学计算机与控制工程学院 *All right reserved. *文件名称:负数把正数赶出队列.cpp *作者:张冰 *完成日期;2016年10月09日 *版本号;v1.0 * *问题描述: 设从键盘输入一整数序列a1,a2,…an,试编程实现: 当ai>0时,ai进队,当ai<0时,将队首元素出队,当ai

Linux命名空间学习教程(二) IPC-程序员宅基地

文章浏览阅读150次。本文讲的是Linux命名空间学习教程(二) IPC,【编者的话】Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid、net、ipc、mnt、uts 等命名空间将容器的进程、网络、消息、文件系统和hostname 隔离开。本文是Li..._主机的 ipc 命名空间

adb强制安装apk_adb绕过安装程序强制安装app-程序员宅基地

文章浏览阅读2w次,点赞5次,收藏7次。在设备上强制安装apk。在app已有的情况下使用-r参数在app版本低于现有版本使用-d参数命令adb install -r -d xxx.apk_adb绕过安装程序强制安装app

随便推点

STM32F407 越界问题定位_stm32flash地址越界怎么解决-程序员宅基地

文章浏览阅读290次。如果是越界进入硬件错误中断,MSP 或者 PSP 保存错误地址,跳转前会保存上一次执行的地址,lr 寄存器会保存子函数的地址,所以如果在 HardFault_CallBack 中直接调用 C 语言函数接口会间接修改了 lr,为了解决这个问题,直接绕过 lr 的 C 语言代码,用汇编语言提取 lr 寄存器再决定后面的操作。由于 STM32 加入了 FreeRTOS 操作系统,可能导致无法准确定位,仅供参考(日常编程需要考虑程序的健壮性,特别是对数组的访问,非常容易出现越界的情况)。_stm32flash地址越界怎么解决

利用SQL注入上传木马拿webshell-程序员宅基地

文章浏览阅读1.8k次。学到了一种操作,说实话,我从来没想过还能这样正常情况下,为了管理方便,许多管理员都会开放MySQL数据库的secure_file_priv,这时就可以导入或者导出数据当我如图输入时,就会在D盘创建一个名为123456.php,内容为<?php phpinfo();?>的文件我们可以利用这一点运用到SQL注入中,从拿下数据库到拿下目标的服务器比如我们在使用联合查询注入,正常是这样的语句http://xxx?id=-1 union select 1,'你想知道的字段的内容或查询语句',

Html CSS的三种链接方式_html链接css代码-程序员宅基地

文章浏览阅读2.9w次,点赞12次,收藏63次。感谢原文:https://blog.csdn.net/abc5382334/article/details/24260817感谢原文:https://blog.csdn.net/jiaqingge/article/details/52564348Html CSS的三种链接方式css文本的链接方式有三种:分别是内联定义、链入内部css、和链入外部css1.代码为:<html>..._html链接css代码

玩游戏哪款蓝牙耳机好?2021十大高音质游戏蓝牙耳机排名_适合游戏与运动的高音质蓝牙耳机-程序员宅基地

文章浏览阅读625次。近几年,蓝牙耳机市场发展迅速,越来越多的消费者希望抛弃线缆,更自由地听音乐,对于运动人士来说,蓝牙耳机的便携性显得尤为重要。但目前市面上的大多数蓝牙耳机实际上都是“有线”的,运动过程中产生的听诊器效应会严重影响听歌的感受。而在“真无线”耳机领域,除了苹果的AirPods外,可供选择的产品并不多,而AirPods又不是为运动场景打造的,防水能力非常差。那么对于喜欢运动又想要“自由”的朋友来说,有没有一款产品能够满足他们的需求呢?下面这十款小编专门为大家搜罗的蓝牙耳机或许就能找到适合的!网红击音F1_适合游戏与运动的高音质蓝牙耳机

iOS 17 测试版中 SwiftUI 视图首次显示时状态的改变导致动画“副作用”的解决方法-程序员宅基地

文章浏览阅读1k次,点赞6次,收藏7次。在本篇博文中,我们在 iOS 17 beta 4(SwiftUI 5.0)测试版中发现了 SwiftUI 视图首次显示时状态的改变会导致动画“副作用”的问题,并提出多种解决方案。

Flutter 自定义 轮播图的实现_flutter pageview轮播图 site:csdn.net-程序员宅基地

文章浏览阅读1.9k次。  在 上篇文章–Flutter 实现支持上拉加载和下拉刷新的 ListView 中,我们最终实现的效果是在 listView 上面留下了一段空白,本意是用来加载轮播图的,于是今天就开发了一下,希望能给各位灵感。一 、效果如下说一下大体思路   其实图片展示是用的 PageView ,然后,下面的指示器 是用的 TabPageSelector ,当然整体是用 Stack 包裹起来的。1、..._flutter pageview轮播图 site:csdn.net