06 第6章作业 | 嵌入式

198 阅读5分钟

1、编写UART_2串口发送程序时,初始化需要设置哪些参数?

1)确定MCU串口号、所接MCU的引脚:

采用的串口为UART_2,在user.h中宏定义使用的串口名为UART_User,以便增强编程的可移植性 UART2串口对应的引脚为PTA2(发送TX)、PTA3(接收RX)

2)确定串口UART_User的波特率,在main.c中,对其初始化

  • 假设波特率为115200:

    uart_init(UART_User,115200); //初始化串口模块

3)printf的设置:格式化输出函数printf灵活地从串口输出调试信息

  • 在printf头文件中宏定义需要与printf相关联的调试串口号

    #define UART_printf UART_2 //printf函数使用的串口号

2、假设速度为115200,系统时钟为72MHz,波特率寄存器 BRR中的值应该是多少?

波特率 :115200

SystemCoreClock = 72MHz

根据以下代码进行计算波特率寄存器 BRR 中的值:

   //配置波特率
    if(*uart_cr1&(0x1UL<<15) == (0x1UL<<15))             
	    usartdiv = (uint16_t)((SystemCoreClock/115200)*2);
    else
	    usartdiv = (uint16_t)((SystemCoreClock/115200));
    *uart_brr = usartdiv;

需要考虑 OVER8 模式和非 OVER8 模式的情况:

  • 对于 OVER8 模式:

    usartdiv = (uint16_t)((SystemCoreClock / 115200) * 2);

    usartdiv = (uint16_t)((72000000 / 115200) * 2) = (uint16_t)(625.0 * 2) = 1250

  • 对于非 OVER8 模式:

    usartdiv = (uint16_t)(SystemCoreClock / 115200);

    usartdiv = (uint16_t)(72000000 / 115200) = (uint16_t)(625.0) = 625

根据不同的模式,波特率寄存器 BRR 中的值应分别为 1250(OVER8 模式)和 625(非 OVER8 模式)

3、中断向量表在哪个文件中?表中有多少项?给出部分截图。

中断向量表存放在 03_MCU/startup/startup_stm32|431rctx.s 中

Untitled.png

  • 表中共有99个中断,前16个为内核中断,后面的为非内核中断 Untitled (1).png

4、以下是中断源使能函数,假设中断源为TIM6,将函数实例化(写出各项具体数值)。

Untitled (2).png

函数传入参数为IRQn(中断号),因为中断源为TIM6,查表可知 Untitled (3).png

  • TIM6对应接受中断的IRQ号为54,54≥0进入if{}

  • ISER[(((uint32_t)IRQn) >> 5UL)]函数内部实现将IRQ号值右移5位

    • 54>>5=1 , 索引值为1
  • (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)) 确定要设置的位数

    • 54 & 0x1F = 22 , 第22位

简化计算: 54/32=1…22

则将ISER[1]的第22位设置为1

5、假设将UART_2和TIM6交换其在中断向量表中的位置和IRQ号,UART_2可以正常中断吗?

假设将 UART_2 和 TIM6 在中断向量表中的位置和 IRQ 号交换:

UART_2 的中断号将变为 TIM6 的原始中断号—54

TIM6 的中断号将变为 UART_2 的原始中断号—38

如果 UART_2 原本可以正常中断,并且在交换后,其新的中断号没有被其他设备占用,那么 UART_2 仍然可以正常中断。

因为中断号的改变不影响中断控制器 NVIC 的配置,只是改变了中断向量表中的中断函数入口地址。

但是需要注意的是,如果在交换后,新的中断号被其他设备占用,或者相关的中断配置没有正确更新,那么 UART_2 的中断功能可能会受到影响。因此,在进行中断号交换时,需要确保相关的中断配置和中断处理函数都正确更新。

6、实现UART_2串口的接收程序

当收到字符时:

① 在电脑的输出窗口显示下一个字符,如收到A显示B;

② 亮灯:

  • 收到字符G,亮绿灯;

  • 收到字符R,亮红灯;

  • 收到字符B,亮蓝灯;

  • 收到其他字符,不亮灯。

实现方式:

(1) 用构件调用方式实现

  • 核心代码:
//接收字符
ch = uart_re1(UART_User,&flag);

//若接收到字符flag为1,未接收到则为0
if(flag){
    //收到字符时的处理
    switch(ch){
            case 'G': 
                    gpio_set(LIGHT_GREEN,LIGHT_ON);   //亮绿灯
                    gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯
        gpio_set(LIGHT_BLUE,LIGHT_OFF);  // 关闭蓝灯
        break;
            case 'R':
        gpio_set(LIGHT_RED,LIGHT_ON);    // 亮红灯
        gpio_set(LIGHT_GREEN,LIGHT_OFF);  // 关闭绿灯
        gpio_set(LIGHT_BLUE,LIGHT_OFF);   // 关闭蓝灯
        break;
    case 'B':
        gpio_set(LIGHT_BLUE,LIGHT_ON);   // 亮蓝灯
        gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯
        gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
        break;
    default:
        gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯
        gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
        gpio_set(LIGHT_BLUE,LIGHT_OFF);  // 关闭蓝灯

        break;                  
    }
    printf("%c\n",ch+1);//显示下一个字符

  }

}

(2) UART部分用直接地址方式实现(即不调用uart.c中的函数,其他部分如GPIO、中断设置可调用函数)

  • 核心代码:
for(;;)
{
    // 判断接收缓冲区是否满,接受字符
    if (*uart_isr & (0x1UL << 5U)) {
        // 读取接收到的字符
        received_char = (uint8_t)(*uart_rdr & 0xFF);

        // 接收到字符时的处理
        switch (received_char) {
            case 'G':
                gpio_set(LIGHT_GREEN, LIGHT_ON);  // 亮绿灯
                gpio_set(LIGHT_RED, LIGHT_OFF);    // 关闭红灯
                gpio_set(LIGHT_BLUE, LIGHT_OFF);   // 关闭蓝灯
                printf("接收:%c【绿灯】\n",received_char);
                break;
            case 'R':
                gpio_set(LIGHT_RED, LIGHT_ON);    // 亮红灯
                gpio_set(LIGHT_GREEN, LIGHT_OFF);  // 关闭绿灯
                gpio_set(LIGHT_BLUE, LIGHT_OFF);   // 关闭蓝灯
                 printf("接收:%c【红灯】\n",received_char);
                break;
            case 'B':
                gpio_set(LIGHT_BLUE, LIGHT_ON);   // 亮蓝灯
                gpio_set(LIGHT_RED, LIGHT_OFF);    // 关闭红灯
                gpio_set(LIGHT_GREEN, LIGHT_OFF);  // 关闭绿灯
                 printf("接收:%c【蓝灯】\n",received_char);
                break;
            default:
                // 收到其他字符不亮灯
                gpio_set(LIGHT_RED, LIGHT_OFF);
                gpio_set(LIGHT_GREEN, LIGHT_OFF);
                gpio_set(LIGHT_BLUE, LIGHT_OFF);
                 printf("接收:%c【不亮灯】\n",received_char);
                break;
            }
             printf("显示:%c\n",received_char+1);
        }

}