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