嵌入式系统原理与实践——第三四次实验

This commit is contained in:
423A35C7 2024-11-04 15:18:33 +08:00
parent 097829e0cc
commit 4deff55942
3 changed files with 604 additions and 0 deletions

View File

@ -5,4 +5,6 @@
\tableofcontents
\subfile{第一次作业——时钟滴答}
\subfile{第二次作业——流水灯}
\subfile{第三次实验——七段数码管}
\subfile{第四次实验——独立按键}
\end{document}

View File

@ -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}

View File

@ -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<stdint.h>
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}