slint esp32 tokio

源碼:https://github.com/xiaguangbo/slint_esp32_tokio
cpu 是 esp32c2,屏幕是 ili9341,觸摸是 xpt2046,使用 spi 半雙工
不使用DMA(esp-rs還沒支持),SPI 40M,240*320全屏刷新為1.5秒,雖然比不了 lvgl,但類lvgl的slint是目前rust跨全平臺唯一的選擇
這是一個游戲,翻到兩個一樣的就成功,slint官網有入門示例,就是這個,然后把 .slint 和 控制邏輯拿過來直接用。就是slint平臺需要稍微移植下,字體會自動打包
在這里插入圖片描述

Cargo.toml

[package]
name = "esp32c2"
version = "0.1.0"
authors = ["xxx"]
edition = "2021"
resolver = "2"
rust-version = "1.71"[profile.release]
opt-level = "s"[profile.dev]
debug = true    # Symbols are nice and they don't increase the size on Flash
opt-level = "z"[features]
default = ["std", "embassy", "esp-idf-svc/native"]pio = ["esp-idf-svc/pio"]
std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"]
alloc = ["esp-idf-svc/alloc"]
nightly = ["esp-idf-svc/nightly"]
experimental = ["esp-idf-svc/experimental"]
embassy = ["esp-idf-svc/embassy-sync","esp-idf-svc/critical-section","esp-idf-svc/embassy-time-driver",
][dependencies]
log = { version = "*", default-features = false }
esp-idf-svc = { version = "*", default-features = false }tokio = { version = "*", features = ["rt", "time", "sync"] }
num-traits = "*"
chrono = "*"
rand = "*"
slint = { version = "*", default-features = false, features = ["compat-1-2","renderer-software","unsafe-single-threaded",
] }[build-dependencies]
embuild = "*"
slint-build = "*"

appwindow.slint

struct TileData {image: image,image_visible: bool,solved: bool,
}component MemoryTile inherits Rectangle {in property <bool> open_curtain;in property <bool> solved;in property <image> icon;callback clicked;height: 50px;width: 50px;border-radius: self.width / 2;background: solved ? #34CE57 : #3960D5;clip: true;animate background { duration: 800ms; }Image {source: icon;width: parent.width;height: parent.height;}// Left curtainRectangle {background: #193076;x: 0px;width: open_curtain ? 0px : (parent.width / 2);height: parent.height;clip: true;animate width {duration: 250ms;easing: ease-in;}Image {width: root.width - 25px;height: root.height - 25px;x: 13px;y: 13px;source: @image-url("../icons/tile_logo.png");}}// Right curtainRectangle {background: #193076;x: open_curtain ? parent.width : (parent.width / 2);width: open_curtain ? 0px : (parent.width / 2);height: parent.height;clip: true;animate width {duration: 250ms;easing: ease-in;}animate x {duration: 250ms;easing: ease-in;}Image {width: root.width - 25px;height: root.height - 25px;x: parent.width - self.width - 13px;y: 13px;source: @image-url("../icons/tile_logo.png");}}TouchArea {clicked => {// Delegate to the user of this elementroot.clicked();}width: 100%;height: 100%;}
}export component AppWindow inherits Window {width: 240px;height: 320px;callback check_if_pair_solved();// Addedin property <bool> disable_tiles;// Addedin-out property <[TileData]> memory_tiles: [{ image: @image-url("../icons/at.png") },{ image: @image-url("../icons/balance-scale.png") },{ image: @image-url("../icons/bicycle.png") },{ image: @image-url("../icons/bus.png") },{ image: @image-url("../icons/cloud.png") },{ image: @image-url("../icons/cogs.png") },{ image: @image-url("../icons/motorcycle.png") },{ image: @image-url("../icons/video.png") },];for tile[i] in memory_tiles: MemoryTile {x: mod(i, 4) * (root.width / 4);y: floor(i / 4) * (root.width / 4);width: 50px;height: 50px;icon: tile.image;open_curtain: tile.image_visible || tile.solved; // 任何一個滿足都打開簾子// propagate the solved status from the model to the tilesolved: tile.solved;clicked => {// old: tile.image_visible = !tile.image_visible;// new:// 可不可以點擊if (!root.disable_tiles) {tile.image_visible = !tile.image_visible;root.check_if_pair_solved();}}}
}

ui

use std::{borrow::Borrow, cell::RefCell, rc::Rc};use slint::platform::{software_renderer::*, PointerEventButton, WindowAdapter, WindowEvent};
use slint::Model;
use tokio::time;use esp_idf_svc::hal::{gpio::*, peripheral::*, spi::*};use crate::component::{ili9341, xpt2046};slint::include_modules!();pub async fn work<SPI, CS, CS2, DC>(spi1: SPI, spi2: SPI, cs1: CS, cs2: CS2, dc: DC)
whereSPI: Borrow<SpiDriver<'static>> + 'static,CS: Peripheral<P = CS> + OutputPin,CS2: Peripheral<P = CS2> + OutputPin,DC: Peripheral<P = DC> + OutputPin,
{let mut ili9341 = ili9341::ILI9341::new(spi1, cs1, dc);let xpt2046 = xpt2046::XPT2046::new(spi2, cs2);ili9341.open();let buffer_provider = DrawBuffer {display: ili9341,buffer: vec![Rgb565Pixel::default(); ili9341::ILI9341_WIDTH as usize].leak(),};slint::platform::set_platform(Box::new(SlintBackend {window: Default::default(),now: std::time::Instant::now().into(),buffer_provider: buffer_provider.into(),touch: xpt2046.into(),last_touch: None.into(),})).unwrap();let main_window = AppWindow::new().unwrap();// Fetch the tiles from the modellet mut tiles: Vec<TileData> = main_window.get_memory_tiles().iter().collect();// Duplicate them to ensure that we have pairstiles.extend(tiles.clone());// Randomly mix the tilesuse rand::seq::SliceRandom;let mut rng = rand::thread_rng();tiles.shuffle(&mut rng);// Assign the shuffled Vec to the model propertylet tiles_model = std::rc::Rc::new(slint::VecModel::from(tiles));main_window.set_memory_tiles(tiles_model.clone().into());let main_window_weak = main_window.as_weak();// 點擊的回調函數main_window.on_check_if_pair_solved(move || {// 如果元素的(image_visible && !solved)為真,則得到他// 就是被打開看的且沒有被標記的對象let mut flipped_tiles = tiles_model.iter().enumerate().filter(|(_, tile)| tile.image_visible && !tile.solved);// 當檢查出有兩個這樣的元素就進入判斷if let (Some((t1_idx, mut t1)), Some((t2_idx, mut t2))) =(flipped_tiles.next(), flipped_tiles.next()){let is_pair_solved = t1 == t2; // 比較兩個元素的值是不是一樣的,包括圖片的 rgba 和元素屬性,也就是 TileData 的所有成員// 一樣if is_pair_solved {t1.solved = true; // 徹底打開簾子tiles_model.set_row_data(t1_idx, t1);t2.solved = true;tiles_model.set_row_data(t2_idx, t2);}// 不一樣else {let main_window = main_window_weak.unwrap();main_window.set_disable_tiles(true); // 防止繼續點擊let tiles_model = tiles_model.clone();// 延時 1sslint::Timer::single_shot(std::time::Duration::from_secs(1), move || {main_window.set_disable_tiles(false); // 可繼續點擊t1.image_visible = false; // 關閉簾子tiles_model.set_row_data(t1_idx, t1);t2.image_visible = false;tiles_model.set_row_data(t2_idx, t2);});}}});loop {slint::run_event_loop().unwrap();time::sleep(time::Duration::from_millis(20)).await;}
}pub struct SlintBackend<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{window: RefCell<Option<Rc<MinimalSoftwareWindow>>>,now: RefCell<std::time::Instant>,buffer_provider: RefCell<DrawBuffer<'a, SPI, DC>>,touch: RefCell<xpt2046::XPT2046<'a, SPI>>,last_touch: RefCell<Option<slint::LogicalPosition>>,
}impl<'a, SPI, DC> slint::platform::Platform for SlintBackend<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, slint::PlatformError> {let window = MinimalSoftwareWindow::new(RepaintBufferType::ReusedBuffer);self.window.replace(Some(window.clone()));self.window.borrow().as_ref().unwrap().set_size(slint::PhysicalSize::new(ili9341::ILI9341_WIDTH as u32,ili9341::ILI9341_HEIGHT as u32,));Ok(window)}fn duration_since_start(&self) -> std::time::Duration {self.now.borrow().elapsed()}fn run_event_loop(&self) -> Result<(), slint::PlatformError> {let while_now = std::time::Instant::now();let mut touch_now = std::time::Instant::now();let mut touch_ed = false;// 連續繪制達到 100ms 就跳過while while_now.elapsed().as_millis() < 100 {slint::platform::update_timers_and_animations();if let Some(window) = self.window.borrow().clone() {if !touch_ed {touch_ed = !touch_ed;touch_now = std::time::Instant::now();if let Some(event) = match self.touch.borrow_mut().read() {Some(v) => {let position = slint::PhysicalPosition::new((v.x * ili9341::ILI9341_WIDTH as f32) as i32,(v.y * ili9341::ILI9341_HEIGHT as f32) as i32,).to_logical(window.scale_factor());Some(match self.last_touch.borrow_mut().replace(position) {Some(_) => WindowEvent::PointerMoved { position },_ => WindowEvent::PointerPressed {position,button: PointerEventButton::Left,},})}_ => self.last_touch.borrow_mut().take().map(|position| {WindowEvent::PointerReleased {position,button: PointerEventButton::Left,}}),} {let is_pointer_release_event =matches!(event, WindowEvent::PointerReleased { .. });window.dispatch_event(event);if is_pointer_release_event {window.dispatch_event(WindowEvent::PointerExited);}}} else {if touch_now.elapsed().as_millis() >= 20 {// 每隔一段時間才能再次讀取觸摸,避免頻繁處理touch_ed = !touch_ed;}}window.draw_if_needed(|renderer| {renderer.render_by_line(&mut *self.buffer_provider.borrow_mut());});if !window.has_active_animations() {// 如果沒有需要繪制的東西就跳出,否則就繼續繪制break;}}}Ok(())}
}struct DrawBuffer<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{display: ili9341::ILI9341<'a, SPI, DC>,buffer: &'a mut [Rgb565Pixel],
}impl<'a, SPI, DC> LineBufferProvider for &mut DrawBuffer<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{type TargetPixel = Rgb565Pixel;fn process_line(&mut self,line: usize,range: std::ops::Range<usize>,render_fn: impl FnOnce(&mut [Rgb565Pixel]),) {let buffer = &mut self.buffer[range.clone()];render_fn(buffer);self.display.write_pixel_slint(range.start as u16,line as u16,range.end as u16,line as u16,&buffer,);}
}

work

use std::{rc, thread};use tokio::{runtime, task, time};use esp_idf_svc::hal::{gpio, peripherals, spi};use crate::module::*;pub fn work() {thread::Builder::new().stack_size(8 * 1024).spawn(|| {task::LocalSet::new().block_on(&runtime::Builder::new_current_thread().enable_all().build().unwrap(),async {let peripherals = peripherals::Peripherals::take().unwrap();let spi = spi::SpiDriver::new::<spi::SPI2>(peripherals.spi2,peripherals.pins.gpio0,peripherals.pins.gpio1,Option::<gpio::AnyIOPin>::None,&spi::SpiDriverConfig::new(),).unwrap();let spi = rc::Rc::new(spi);let spi_1 = spi.clone();let spi_2 = spi.clone();task::spawn_local(async move {ui::work(spi_1,spi_2,peripherals.pins.gpio3,peripherals.pins.gpio4,peripherals.pins.gpio2,).await;});loop {time::sleep(time::Duration::MAX).await;}},);}).unwrap();
}

build

fn main() {embuild::espidf::sysenv::output();slint_build::compile_with_config("ui/appwindow.slint",slint_build::CompilerConfiguration::new().embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer),).unwrap();
}

ili9341

use std::borrow::*;use esp_idf_svc::hal::{delay::Delay, gpio::*, peripheral::*, prelude::*, spi::*};use slint::platform::software_renderer::Rgb565Pixel;pub const ILI9341_WIDTH: u16 = 240;
pub const ILI9341_HEIGHT: u16 = 320;/*
# 初始化
第一個字節是命令
等待5ms36, 48 左上右下豎屏、c8 右下左上豎屏、e8 左下右上橫屏、28右上左下橫屏
3a, 55 像素格式 565
11     退出睡眠
29     開顯示、28 關顯示。不會更改內存內容# 設置區域
可設置一點、一行或一個方塊,方塊區域會自動換行2a x坐標
16bit xs
16bit xe2b y坐標
16bit ys
16bit ye2c
16bit 565 顏色數據
*/pub struct ILI9341<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{spi: SpiDeviceDriver<'a, SPI>,dc: PinDriver<'a, DC, Output>,line_buf: Vec<u8>,
}impl<'a, SPI, DC> ILI9341<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{pub fn new<CS>(spi: SPI, cs: CS, dc: DC) -> SelfwhereCS: Peripheral<P = CS> + OutputPin,{let config = config::Config::default().baudrate(40.MHz().into()).duplex(config::Duplex::Half3Wire);Self {spi: SpiDeviceDriver::new(spi, Some(cs), &config).unwrap(),dc: PinDriver::output(dc).unwrap(),line_buf: vec![0u8; (ILI9341_WIDTH * 2) as usize],}}pub fn open(&mut self) {let delay = Delay::new_default();for _ in 0..2 {delay.delay_ms(20);self.write_cmd_data_u8(0x36, Some(&[0x48]));self.write_cmd_data_u8(0x3a, Some(&[0x55]));self.write_cmd_data_u8(0x11, None);self.write_cmd_data_u8(0x29, None);}}pub fn write_pixel_slint(&mut self,x: u16,y: u16,x_end: u16,y_end: u16,pixel: &[Rgb565Pixel],) {self.write_draw_range(x, y, x_end, y_end);self.write_cmd_data_slint(0x2c, pixel);}fn write_cmd_data_u8(&mut self, cmd: u8, data: Option<&[u8]>) {self.dc.set_low().unwrap();self.spi.write(&[cmd]).unwrap();if let Some(v) = data {self.dc.set_high().unwrap();self.spi.write(v).unwrap();}}fn write_draw_range(&mut self, x: u16, y: u16, x_end: u16, y_end: u16) {let mut x_buf = [0u8; 4];let mut y_buf = [0u8; 4];x_buf[0..=1].copy_from_slice(&x.to_be_bytes());x_buf[2..=3].copy_from_slice(&x_end.to_be_bytes());y_buf[0..=1].copy_from_slice(&y.to_be_bytes());y_buf[2..=3].copy_from_slice(&y_end.to_be_bytes());self.write_cmd_data_u8(0x2a, Some(&x_buf));self.write_cmd_data_u8(0x2b, Some(&y_buf));}fn write_cmd_data_slint(&mut self, cmd: u8, data: &[Rgb565Pixel]) {let mut i = 0;data.iter().for_each(|v| {self.line_buf[i..=i + 1].copy_from_slice(v.0.to_be_bytes().as_ref());i += 2;});self.dc.set_low().unwrap();self.spi.write(&[cmd]).unwrap();self.dc.set_high().unwrap();self.spi.write(self.line_buf[0..i].as_ref()).unwrap();}
}

xpt2046

use std::borrow::*;use esp_idf_svc::hal::{gpio::*, peripheral::*, prelude::*, spi::*};/*
d0 讀 x 軸
90 讀 y 軸
*/pub struct XPT2046Touch {pub x: f32,pub y: f32,
}pub struct XPT2046<'a, SPI>
whereSPI: Borrow<SpiDriver<'a>> + 'a,
{spi: SpiDeviceDriver<'a, SPI>,
}impl<'a, SPI> XPT2046<'a, SPI>
whereSPI: Borrow<SpiDriver<'a>> + 'a,
{pub fn new<CS>(spi: SPI, cs: CS) -> SelfwhereCS: Peripheral<P = CS> + OutputPin,{let config = config::Config::default().baudrate(2.MHz().into()).duplex(config::Duplex::Half3Wire);Self {spi: SpiDeviceDriver::new(spi, Some(cs), &config).unwrap(),}}pub fn read(&mut self) -> Option<XPT2046Touch> {let mut x_u16 = [0u16; 3];let mut y_u16 = [0u16; 3];for i in 0..x_u16.len() {let mut x = [0u8; 2];let mut y = [0u8; 2];self.spi.transaction(&mut [Operation::Write(&[0xd0]), Operation::Read(&mut x)]).unwrap();self.spi.transaction(&mut [Operation::Write(&[0x90]), Operation::Read(&mut y)]).unwrap();x_u16[i] = u16::from_be_bytes(x) << 1 >> 4;y_u16[i] = u16::from_be_bytes(y) << 1 >> 4;}x_u16.sort();y_u16.sort();// 實測最大最小值let x = x_u16[1].max(336).min(3847);let y = y_u16[1].max(184).min(3584);let x = (x - 336) as f32 / (3847 - 336) as f32;let y = (y - 184) as f32 / (3584 - 184) as f32;// 判斷有沒有觸摸if x == 0 as f32 && y == 1 as f32 {None} else {Some(XPT2046Touch { x, y })}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/16198.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/16198.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/16198.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python文件IO之pickle 模塊讀寫對象數據

可以向一個文件中寫入字符串&#xff0c;讀取后也是讀取字符串形式&#xff0c;但是不能直接向文件中寫入像列表這樣的對象&#xff0c;需要 pickle 等模塊才行。 pickle 模塊介紹 pickle 模塊使用強大且有效的算法來進行序列化和反序列化。 序列化是指將一個對象轉換為能夠存…

前端面試手冊

前端面試手冊 崗位職責&#xff1a; 1&#xff0e;熟悉公司業務&#xff0c;能獨立高效高質地完成任務&#xff0c;負責功能的開發、測試、上線、維護&#xff1b; 2&#xff0e;負責推動、優化前端基礎架構、組件抽象&#xff0c;提升開發效率&#xff1b; 3&#xff0e;關…

四. TensorRT模型部署優化-模型部署的基礎知識

目錄 前言0. 簡介1. FLOPS2. TOPS3. HPC的排行&#xff0c;CPU/GPU比較4. FLOPs5. FLOPS是如何計算的6. CUDA Core vs Tensor Core總結參考 前言 自動駕駛之心推出的 《CUDA與TensorRT部署實戰課程》&#xff0c;鏈接。記錄下個人學習筆記&#xff0c;僅供自己參考 本次課程我們…

記一次Spark cache table導致的數據問題以及思考

目前在做 Spark 升級(3.1.1升級到3.5.0)的時候&#xff0c;遇到了cache table導致的數據重復問題&#xff0c;這種情況一般來說是很少見的&#xff0c;因為一般很少用cache table語句。 當然該問題已經在Spark3.5.1已經解決了,可以查看對應的 SPARK-46995和SPARK-45592 從以上的…

最小二乘法-超詳細推導(轉換為矩陣乘法推導,矩陣求導推導)

最小二乘法就是讓均方誤差最小。 下面是損失函數轉換為矩陣方式的詳解 如何讓其最小&#xff0c;在導數為0的地方取極小值。 問&#xff1a;導數為0的地方可能去極大值&#xff0c;也可能是極小值&#xff0c;憑什么說導數為0就是極小值&#xff1f; 答&#xff1a;因為使用…

android ndc firewall 命令type 黑名單 白名單差異

可以看到以白名單方式使能防火墻&#xff0c;fw_FORWARD fw_INPUT fw_OUTPUT 的操作是DROP或REJEDCT。即默認所有應用不允許上網&#xff0c;需要 XXX:/ # ndc firewall enable whitelist 200 0 Firewall command succeeded XXX:/ # iptables -t filter -L Chain INPUT (polic…

酷黑簡潔大氣體育直播自適應模板賽事直播門戶網站源碼

源碼名稱&#xff1a;酷黑簡潔大氣體育直播自適應模板賽事直播門戶網站源碼 開發環境&#xff1a;帝國cms 7.5 安裝環境&#xff1a;phpmysql 支持PC與手機端同步生成html&#xff08;多端同步生成插件&#xff09; 帶軟件采集&#xff0c;可以掛著自動采集發布&#xff0c;無…

【HSQL001】HiveSQL內置函數手冊總結(更新中)

1.熟悉、梳理、總結下Hive SQL相關知識體系。 2.日常研發過程中使用較少&#xff0c;隨著時間的推移&#xff0c;很快就忘得一干二凈&#xff0c;所以梳理總結下&#xff0c;以備日常使用參考 3.歡迎批評指正&#xff0c;跪謝一鍵三連&#xff01; 文章目錄 1.函數清單 1.函數清…

某某某加固系統分析

某某某加固系統內核so dump和修復&#xff1a; 某某某加固系統采取了內外兩層native代碼模式&#xff0c;外層主要為了保護內層核心代碼&#xff0c;從分析來看外層模塊主要用來反調試&#xff0c;釋放內層模塊&#xff0c;維護內存模塊的某些運行環境達到防止分離內外模塊&am…

網上比較受認可的賺錢軟件有哪些?眾多兼職選擇中總有一個適合你

在這個互聯網高速發展的時代&#xff0c;網上賺錢似乎成了一種潮流。但是&#xff0c;你是否還在靠運氣尋找賺錢的機會&#xff1f;是否還在為找不到靠譜的兼職平臺而苦惱&#xff1f; 今天&#xff0c;就為你揭秘那些真正靠譜的網上賺錢平臺&#xff0c;讓你的賺錢之路不再迷…

等保測評的流程是怎樣的

等保測評概述 等保測評&#xff0c;即信息安全等級保護測評&#xff0c;是指對信息系統安全性能進行等級評估的過程。其目的是通過評估系統的安全性能&#xff0c;為系統提供一個安全等級&#xff0c;并規定相應的保護措施。等保測評的流程通常包括定級、備案、安全建設、等級測…

Python--List列表

list列表?? 1高級數據類型 Python中的數據類型可以分為&#xff1a;數字型&#xff08;基本數據類型&#xff09;和非數字型&#xff08;高級數據類型&#xff09; ●數字型包含&#xff1a;整型int、浮點型float、布爾型bool、復數型complex ●非數字型包含&#xff1a;字符…

TypeScript-type注解對象類型

type注解對象類型 在TS中對于對象數據的類型注解&#xff0c;除了使用interface之外還可以使用類型別名來進行注解&#xff0c;作用類似 type Person {name: stringage: number }const p:Person {name: lily,age: 16 } type 交叉類型&模擬繼承 類型別名配合交叉類型…

docker創建的rabbitmq,啟動容器時報:Failed to create thread: Operation not permitted (1)

原因&#xff1a;docker內的用戶權限受限 啟動docker時加上參數 --privilegedtrue docker run --privilegedtrue -d --name rabbitmq --restartalways -p 5671:5671 -p 5672:5672 -p 15672:15672 -p 15671:15671 -p 25672:25672 -v /home/rabbitmq/data/:/var/rabbitm…

整合SSM框架筆記

整合SSM框架筆記 Spring5 Spring MVC MyBatis Druid MySQL Thymeleaf 感謝尚硅谷課程&#xff1a;B站課程 前言 單Spring框架時&#xff0c;是Java工程。 Spring與Spring MVC可以共用一個配置文件&#xff0c;也可以不共用一個&#xff0c;推薦不共用一個。 Spring與Sp…

Quartus 聯合 ModelSim 仿真 IP 核(RAM)

文章目錄 ModelSim 路徑設置創建 RAM進行仿真 本文主要介紹如何在包含 IP 核的 Quartus 項目中使用 Modelsim 進行仿真&#xff0c;本文基于 IP 核 RAM: 2-PORT&#xff0c;其他 IP 核類似。 ModelSim 路徑設置 點擊 Tools->Options 點擊 EDA Tool Options&#xff0c;設置…

BeanFactory、FactroyBean、ApplicationContext

BeanFactory Ioc容器、定義接口規范來管理spring bean的生命周期、依賴、注入&#xff0c;spring中有各種Ioc容器 FactroyBean 定制的工廠Bean&#xff0c;可以通過抽象工廠方式創建的bean&#xff0c;不納入spring的生命周期、依賴、注入特性&#xff0c;相當于spring給第三…

string OJ題

下面分享一下string做題心得 1. 明白字符串中存儲的數字為0 8 9與0 8 9 完全不同&#xff0c;字符0其實在串中存儲的是48&#xff0c;要有意識的轉化。字符串中如果存數字8&#xff0c;意味著存了BS&#xff08;退格&#xff09; 例如1&#xff1a; 算出結果為5&#xff0c;存…

MySQL 用戶變量賦值、查詢賦值、滾動賦值

在MySQL中&#xff0c;用戶變量是一種在會話級別存儲和重用值的方式&#xff0c;它們以符號開頭。用戶變量可以在查詢中用來存儲和傳遞數據&#xff0c;增強SQL腳本的功能性。 定義和賦值用戶變量用戶變量可以直接在查詢中定義并賦值&#xff0c;不需要預先聲明。賦值可以使用S…

springboot+mybatis+druid 配置單實例多數據源

第一步&#xff1a;pom中添加依賴 <!--mybatis多數據源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>2.5.6</version></dependency> 第…