diff --git a/嵌入式系统原理与实践/实验报告/全部作业.tex b/嵌入式系统原理与实践/实验报告/全部作业.tex index d44c64d..02e2e4b 100644 --- a/嵌入式系统原理与实践/实验报告/全部作业.tex +++ b/嵌入式系统原理与实践/实验报告/全部作业.tex @@ -5,4 +5,6 @@ \tableofcontents \subfile{第一次作业——时钟滴答} \subfile{第二次作业——流水灯} + \subfile{第三次实验——七段数码管} + \subfile{第四次实验——独立按键} \end{document} \ No newline at end of file diff --git a/嵌入式系统原理与实践/实验报告/第三次实验——七段数码管.tex b/嵌入式系统原理与实践/实验报告/第三次实验——七段数码管.tex new file mode 100644 index 0000000..ad6cc6f --- /dev/null +++ b/嵌入式系统原理与实践/实验报告/第三次实验——七段数码管.tex @@ -0,0 +1,199 @@ +\documentclass[全部作业]{subfiles} + +\begin{document} + +\date{2024年11月3日} +\begin{frame} + %\maketitle + \titlepage +\end{frame} + +\begin{frame} + \frametitle{目录} + \tableofcontents +\end{frame} + +\section{第三次实验} + +\subsection{准备} +\begin{frame}[fragile] + 将实验二的代码复制一份,并将exp2改名为exp3: + \vspace{1em} + + \begin{minipage}[H]{0.3\linewidth} + \begin{minted}[linenos=false]{text} +exp2 +│ .mxproject +│ exp2.ioc +│ +├─Core +│ +├─Drivers +│ +└─MDK-ARM + exp2.uvprojx + startup_stm32g473xx.s + \end{minted} + \end{minipage} + {\Huge$\longrightarrow$} + \begin{minipage}[H]{0.3\linewidth} + \begin{minted}[linenos=false]{text} + exp3 + │ .mxproject + │ exp3.ioc + │ + ├─Core + │ + ├─Drivers + │ + └─MDK-ARM + exp3.uvprojx + startup_stm32g473xx.s + \end{minted} + \end{minipage} + \vspace{1em} + + 需要改文件夹名、.ioc、.uvprojx这三个地方。 +\end{frame} + +\begin{frame} + 打开.uvprojx文件,修改调试器: + \includegraphics{imgs/2024-10-29-11-36-58.png} + \vspace{1em} + + \includegraphics[width=1\linewidth]{imgs/2024-10-29-11-35-44.png} +\end{frame} + +\begin{frame} + 修改调试设置,把reset and run打勾,就不需要手动按重置按钮了。 + \includegraphics[width=1\linewidth]{imgs/2024-10-29-14-54-11.png} +\end{frame} + +\subsection{端口修改} +\begin{frame} + 这样设置端口,点击生成代码。 + \includegraphics[width=0.8\linewidth]{imgs/2024-11-03-13-47-47.png} +\end{frame} + +\begin{frame} + 将 STM32 核心板 JP1 的 PA0$\sim$PA7 与系统的七段数码管电路的 JP19 相连,PA0$\sim$PA7 分别对应于JP19的D0$\sim$D7,用1x4的杜邦线将STM32核心板的JP2的PB0$\sim$PB3 分别连接到系统底板上JP20的A、B、C和OE接口。 + + \includegraphics[width=0.2\linewidth]{imgs/IMG_20241103_194712_1.jpg} + \includegraphics[width=0.2\linewidth]{imgs/IMG_20241103_194932.jpg} + \includegraphics[width=0.2\linewidth]{imgs/IMG_20241103_144021.jpg} + \includegraphics[width=0.2\linewidth]{imgs/IMG_20241103_144035.jpg} +\end{frame} + +\subsection{代码修改} +\begin{frame}[fragile] + main.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=45]{C} +/* USER CODE BEGIN PV */ +stSysTickTimer sSysTickTimer = { + 0, 0, 0, 0 +}; +uint16_t display_tab[] = { + 0x3f, + 0x06, + 0x5b, + 0x4f, + 0x66, + 0x6d, + 0x7d, + 0x07, + 0x7f, + 0x6f, + 0x77, + 0x7c, + 0x39, + 0x5e, + 0x79, + 0x71 +}; +uint16_t PosSel = 0; +/* USER CODE END PV */ + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] + main.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=117]{C} + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + if (sSysTickTimer.bTimeOk) { + sSysTickTimer.bTimeOk = 0; + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + } + // if (sSysTickTimer.bTenMilSecOk) { + SegLedData_GPIO_Port->ODR = 0x00; + AddrA_GPIO_Port->ODR = PosSel; + SegLedData_GPIO_Port->ODR = display_tab[PosSel % 8]; + if (++PosSel >= 8) { + PosSel = 0; + } + // } + } + /* USER CODE END 3 */ + \end{minted} + \end{multicols} +\end{frame} + + +\subsection{思考题} +\begin{frame}[fragile] + 我们的需求是将数字一位一位向前推进,那么考虑现在的位选信号(控制哪一位上显示数字)与段选信号(控制显示哪个数字)之间的关系,根据 \mintinline{C}{SegLedData_GPIO_Port->ODR = display_tab[PosSel % 8];} + 可知 + $$ + \text{段选信号}_0=f(\text{位选信号}_0) + $$ + 而修改后就变成了(时间用$t$表示) + $$ + \text{段选信号}_{t}=g(\text{位选信号}_{t}, t) + $$ + 因此,只需要加一个随时间变化的变量,例如 $bias = bias(t)$,再把之前的f看做是时间为0时的静止状态,则可以得到 + $$ + \begin{cases} + \text{段选信号}_0=g(\text{位选信号}_0, 0) = h(\text{位选信号}_0, bias(0)) = f(\text{位选信号}_0) \\ + \text{段选信号}_{t}=g(\text{位选信号}_{t}, t) = h(\text{位选信号}_{t}, bias(t)) \\ + \end{cases} + $$ + 其中的$h$和$bias$就是我们需要构造的函数和变量。 +\end{frame} + +\begin{frame}[fragile] + 确定$bias(0)$的值: + \begin{minted}[firstnumber=68]{C} +uint8_t bias = 0; + \end{minted} + + 在bTimeOk时改变$bias$的值,使$bias$随时间变化: + \begin{minted}[firstnumber=128]{C} + if (++bias >= 8) { + bias = 0; + } + \end{minted} + + 构造$h(\text{段选信号}, bias)$使得$h(\text{段选信号},0)=f(\text{段选信号})$ + \begin{minted}[firstnumber=136]{C} + SegLedData_GPIO_Port->ODR = display_tab[(PosSel + bias) % 8]; + \end{minted} +\end{frame} + +\subsection{实验结果} +\begin{frame} + 初始显示01234567,每过一秒,数字向左循环移位一位,即 + $$ + 01234567 \to 12345670 \to 23456701 \to \cdots \to 70123456 \to 01234567 + $$ + \includegraphics[width=0.5\linewidth]{imgs/IMG_20241103_162322.jpg} + + 完整视频可以查看:\url{https://gitea.librastalker.top/423A35C7/STM32CubeMX-Keil_uVision5} +\end{frame} +\end{document} \ No newline at end of file diff --git a/嵌入式系统原理与实践/实验报告/第四次实验——独立按键.tex b/嵌入式系统原理与实践/实验报告/第四次实验——独立按键.tex new file mode 100644 index 0000000..d731074 --- /dev/null +++ b/嵌入式系统原理与实践/实验报告/第四次实验——独立按键.tex @@ -0,0 +1,403 @@ +\documentclass[全部作业]{subfiles} + +\begin{document} + +\date{2024年11月3日} +\begin{frame} + %\maketitle + \titlepage +\end{frame} + +\begin{frame} + \frametitle{目录} + \tableofcontents +\end{frame} + +\section{第四次实验} + +\subsection{准备} +\begin{frame}[fragile] + 将实验三的代码复制一份,并将exp3改名为exp4: + \vspace{1em} + + \begin{minipage}[H]{0.3\linewidth} + \begin{minted}[linenos=false]{text} +exp3 +│ .mxproject +│ exp3.ioc +│ +├─Core +│ +├─Drivers +│ +└─MDK-ARM + exp3.uvprojx + startup_stm32g473xx.s + \end{minted} + \end{minipage} + {\Huge$\longrightarrow$} + \begin{minipage}[H]{0.3\linewidth} + \begin{minted}[linenos=false]{text} + exp4 + │ .mxproject + │ exp4.ioc + │ + ├─Core + │ + ├─Drivers + │ + └─MDK-ARM + exp4.uvprojx + startup_stm32g473xx.s + \end{minted} + \end{minipage} + \vspace{1em} + + 需要改文件夹名、.ioc、.uvprojx这三个地方。 +\end{frame} + +\begin{frame} + 打开.uvprojx文件,修改调试器: + \includegraphics{imgs/2024-10-29-11-36-58.png} + \vspace{1em} + + \includegraphics[width=1\linewidth]{imgs/2024-10-29-11-35-44.png} +\end{frame} + +\begin{frame} + 修改调试设置,把reset and run打勾,就不需要手动按重置按钮了。 + \includegraphics[width=1\linewidth]{imgs/2024-10-29-14-54-11.png} +\end{frame} + +\subsection{端口修改} +\begin{frame} + 这样设置端口,点击生成代码。 + \includegraphics[width=1\linewidth]{imgs/2024-11-03-20-18-38.png} +\end{frame} + +\begin{frame} + 按键: + (Key1、Key5、Key9和Key13的四个按键的一个端子与JP15的KL0$\sim $KL3相连。)核心板JP1 的 PB0$\sim$PB3 接 底板JP15 的 KL0$\sim$KL3。将JP16上面两个引脚的跳线帽拔下来插到下面两个引脚(即BTN)。 + + \includegraphics[width=0.3\linewidth]{imgs/IMG_20241103_194951_1.jpg} + \includegraphics[width=0.3\linewidth]{imgs/IMG_20241103_195542_1.jpg} + \includegraphics[width=0.3\linewidth]{imgs/IMG_20241103_195612.jpg} +\end{frame} + +\begin{frame} + 数码管: + 将 STM32 核心板 JP1 的 PA0$\sim$PA7 与系统的七段数码管电路的 JP19 相连,PA0$\sim$PA7 分别对应于JP19的D0$\sim$D7,用1x4的杜邦线将STM32核心板的JP2的PB0$\sim$PB3 分别连接到系统底板上JP20的A、B、C和OE接口。 + + \includegraphics[width=0.23\linewidth]{imgs/IMG_20241103_194712_1.jpg} + \includegraphics[width=0.23\linewidth]{imgs/IMG_20241103_194932.jpg} + \includegraphics[width=0.23\linewidth]{imgs/IMG_20241103_144021.jpg} + \includegraphics[width=0.23\linewidth]{imgs/IMG_20241103_144035.jpg} +\end{frame} + +\subsection{代码修改} +\begin{frame}[fragile] +添加DirectKey.h: + \begin{multicols}{2} + \begin{minted}[firstnumber=1]{C} +#ifndef __DIRECTKEY_H +#define __DIRECTKEY_H + +#include + +enum {State0=0, State1, State2}; + +#define NoKey 0x0F +#define KeyPort GPIOC + + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t ReadDirectKey(void); + +#ifdef __cplusplus +} +#endif + +#endif + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] + 添加DirectKey.c: + \begin{multicols}{2} + \begin{minted}{C} +#include "directkey.h" +#include "main.h" + + +uint8_t ReadDirectKey(void) { + static uint8_t KeyState = State0; + static uint8_t KeyOld; + uint8_t KeyPress; + uint8_t KeyValue = NoKey; + + KeyPress = KeyPort->IDR & 0x000F; // 读按键 + + switch (KeyState) { + case State0: + if (KeyPress != NoKey) { + KeyOld = KeyPress; // 保存原来的键 + KeyState = State1; // 切换状态 + } + break; + + case State1: + if (KeyPress == KeyOld) { + KeyState = State2; + // KeyValue = KeyOld; // 按下有效 + } else { + KeyState = State0; + } + break; + + case State2: + if (KeyPress == NoKey) { + KeyState = State0; + KeyValue = KeyOld; // 抬起有效 + } else { + } + break; + + default: + break; + } + return KeyValue; +} + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] +stm32g4xx_it.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=182]{C} +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + Display(); + if (++sSysTickTimer.mMilSecCount >= 10) { + sSysTickTimer.mMilSecCount = 0; + sSysTickTimer.bTenMilSecOk = 1; + if (++sSysTickTimer.mTimeCount >= 100) { + sSysTickTimer.mTimeCount = 0; + sSysTickTimer.bTimeOk = 1; + } + } + /* USER CODE END SysTick_IRQn 1 */ +} + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] +main.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=24]{C} +/* USER CODE BEGIN Includes */ +#include "variable.h" +#include "directkey.h" +/* USER CODE END Includes */ + \end{minted} + \vspace{1em} + + \begin{minted}[firstnumber=46]{C} +/* USER CODE BEGIN PV */ +stSysTickTimer sSysTickTimer = { + 0, 0, 0, 0 +}; +uint8_t tempValue; +uint16_t display_tab[] = { + 0x3f, + 0x06, + 0x5b, + 0x4f, + 0x66, + 0x6d, + 0x7d, + 0x07, + 0x7f, + 0x6f, + 0x77, + 0x7c, + 0x39, + 0x5e, + 0x79, + 0x71 +}; +uint8_t DispBuff[8]; +uint16_t PosSel = 0; +/* USER CODE END PV */ + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] +main.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=79]{C} +/* Private user code ----------------------------*/ +/* USER CODE BEGIN 0 */ +void DisplayOneLed(uint8_t dat, uint8_t pos, uint8_t dot) { + uint16_t temp; + + temp = display_tab[dat]; + if (dot) + temp |= 0x80; + + GPIOA->ODR &= 0xFF00; + GPIOA->ODR |= temp; // 数据段 + GPIOB->ODR &= 0xFFF0; + GPIOB->ODR |= pos; // 位选 +} + +void Display(void) { + static uint8_t mPos = 0; + DisplayOneLed(DispBuff[mPos], mPos, 0); + if (++mPos >= 8) mPos = 0; +} + +void TimeToBuff(void) { + uint8_t i; + uint8_t temp; + temp = DispBuff[0]; + for (int i = 0; i < 7; i++) { + DispBuff[i] = DispBuff[i + 1]; + } + DispBuff[7] = temp; +} + +void DispToBuff(uint8_t val) { + uint8_t i; + for (int i = 0; i < 7; i++) { + DispBuff[i] = DispBuff[i + 1]; + } + DispBuff[7] = val; +} +/* USER CODE END 0 */ + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] +main.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=119]{C} +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + + /* USER CODE BEGIN 1 */ + uint8_t KeyValue = 0; + /* 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(); + /* USER CODE BEGIN 2 */ + // FlashLeds_GPIO_Port->ODR &= 0xff01; + for (int i = 0; i < 8; i++) { + DispBuff[i] = i; + } + /* USER CODE END 2 */ + + \end{minted} + \end{multicols} +\end{frame} + +\begin{frame}[fragile] +main.c: + \begin{multicols}{2} + \begin{minted}[firstnumber=last]{C} + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + if (sSysTickTimer.bTenMilSecOk) { + sSysTickTimer.bTenMilSecOk = 0; + KeyValue = ReadDirectKey(); + if (KeyValue != NoKey) { + switch (KeyValue) + { + case 0x0E: // K1 + tempValue = 1; + break; + + case 0x0D: // K5 + tempValue = 2; + break; + + case 0x0B: // K9 + tempValue = 3; + break; + + case 0x07: // K13 + tempValue = 4; + break; + + default: + break; + } + DispToBuff(tempValue); + } + } + if (sSysTickTimer.bTimeOk) { + sSysTickTimer.bTimeOk = 0; + // TimeToBuff(); + HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); + } + } + /* USER CODE END 3 */ +} + \end{minted} + \end{multicols} +\end{frame} + +\subsection{实验结果} +\begin{frame} + 数码管初始显示01234567,按下K1、K5、K9、K13并抬起时,数码管左移一位,并在右侧添加1、2、3、4。因此记K1、K5、K9、K13分别为1、2、3、4。例如,逐个按下1433223,数码管显示的数字变化为: + $$ + 01234567 \to 12345671 \to 23456714 \to \cdots\to 71433223 + $$ + \includegraphics[width=0.45\linewidth]{imgs/IMG_20241103_162322.jpg} + \includegraphics[width=0.45\linewidth]{imgs/IMG_20241103_213225.jpg} + + 完整视频可以查看:\url{https://gitea.librastalker.top/423A35C7/STM32CubeMX-Keil_uVision5} +\end{frame} + +\end{document} \ No newline at end of file