嵌入式第六章作业

1、确定MCU串口号、所接MCU的引脚,UART_2的时钟、UART_2对应的GPIOx端口初始化、UART_2模式初始化(数据位长度、过采样模式、校验、其他模式等)确定串口的波特率。

2、

对于OVER8模式:usartdiv = (uint16_t)((72000000 / 115200) * 2) = (uint16_t)(625.0 * 2) = 1250

对于非OVER8模式:usartdiv = (uint16_t)(72000000 / 115200) = (uint16_t)(625.0) = 625

波特率寄存器BRR中的值分别为1250和625

3、

中断向量表中有99个项。

4、

函数实例化:

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

54>>5=1,索引值为1

(uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)) //确定要设置的位数

54&0x1F=22,第22位

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

5、

假设将UART_2和TIM6交换其在中断向量表中的位置和IRQ号,UART_2可以正常中断,但需要进行一系列的配置和调整,以确保中断能够正确触发并处理。

中断服务程序重新配置:由于UART_2和TIM6在中断向量表中的位置被交换,因此原本为UART_2编写的中断服务程序(ISR)现在将指向TIM6的中断处理函数,而原本为TIM6编写的ISR将指向UART_2的中断处理函数。因此,需要确保这些中断服务程序与新的中断源匹配。中断优先级重新配置:中断优先级顺序可能因为位置和IRQ号的交换而发生变化。因此,需要根据新的设置重新配置中断优先级,以确保紧急的中断能够优先得到处理。重新配置UART2的中断使能:在交换位置后,需要确保为UART2重新设置中断使能,以确保UART2在接收到数据或其他中断事件时能够触发中断。更新NVIC和中断向量表:NVIC(嵌套向量中断控制器)负责中断的调度和处理。因此,需要更新NVIC的设置,以反映UART_2和TIM6新的中断号和中断处理函数。此外,还需要更新中断向量表,确保中断发生时能够正确跳转到相应的中断服务程序。

(1)

#define GLOBLE_VAR

#include "includes.h"      //包含总头文件

int main(void)

{

        uint32_t mMainLoopCount;  //主循环次数变量

        uint8_t  ch;             //临时变量

        uint8_t  flag;             //临时变量

//(1.2)【不变】关总中断

        DISABLE_INTERRUPTS;

//(1.3)给主函数使用的局部变量赋初值

    mMainLoopCount=0;    //主循环次数变量

 

//(1.4)给全局变量赋初值

//(1.5)用户外设模块初始化

        gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF);   //初始化蓝灯

        gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF); //初始化绿灯

        gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF);//初始化红灯

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

 

//(1.6)使能模块中断

//(1.7)【不变】开总中断

        ENABLE_INTERRUPTS;

       

 

//(1)======启动部分(结尾)==========================================

//(2)======主循环部分(开头)========================================

        for(;;)   //for(;;)(开头)

        {

                 mMainLoopCount++;

                 if (mMainLoopCount<=35000000)  continue;

                 mMainLoopCount=0;    //循环次数变量

//(2.3.3)通过调试串口提示

        printf("金葫芦友情提示:\r\n");

       // printf("蓝灯亮暗次数=%d,  关闭本窗体\r\n",mLightCount);

        printf("“工具”→“串口工具”,打开接收User串口数据观察\r\n");

        ch = uart_re1(UART_User,&flag);

if(flag){

    //收到字符时的处理

    switch(ch){

            case 'G':

            gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯

            gpio_set(LIGHT_BLUE,LIGHT_OFF);  // 关闭蓝灯

            gpio_set(LIGHT_GREEN,LIGHT_ON);   //亮绿灯

          

            break;

            case 'R':

            gpio_set(LIGHT_GREEN,LIGHT_OFF);  // 关闭绿灯

            gpio_set(LIGHT_BLUE,LIGHT_OFF);   // 关闭蓝灯

            gpio_set(LIGHT_RED,LIGHT_ON);    // 亮红灯

           

            break;

            case 'B':

            gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯

            gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯

            gpio_set(LIGHT_BLUE,LIGHT_ON);   // 亮蓝灯

          

            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);

  }

}   //main函数(结尾)

(2)

#define GLOBLE_VAR

#include "includes.h"      //包含总头文件

//----------------------------------------------------------------------

//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)

int main(void)

{

    //(1)======启动部分(开头)==========================================

    //(1.1)声明main函数使用的局部变量

    uint8_t  mTest;

    uint32_t mMainLoopCount;

    uint8_t  ch;             //临时变量

       

    //uart寄存器相关地址

    volatile uint32_t* RCC_AHB2;     //GPIO的A口时钟使能寄存器地址

    volatile uint32_t* RCC_APB1;     //UART的2口时钟使能寄存器地址

    volatile uint32_t* gpio_ptr;       //GPIO的A口基地址

    volatile uint32_t* uart_ptr;       //uart2端口的基地址

    volatile uint32_t* gpio_mode;    //引脚模式寄存器地址=口基地址

    volatile uint32_t* gpio_afrl;      //GPIO复用功能低位寄存器

    volatile uint32_t* uart_brr;      //UART波特率寄存器地址

    volatile uint32_t* uart_isr;      // UART中断和状态寄存器基地址

    volatile uint32_t* uart_cr1;      //UART控制寄存器1基地址

    volatile uint32_t* uart_cr2;      // UART控制寄存器2基地址

    volatile uint32_t* uart_cr3;      // UART控制寄存器3基地址

    volatile uint32_t* uart_tdr;      // UART发送数据寄存器

    volatile uint32_t* uart_rdr;      // UART接收数据寄存器

    uint16_t usartdiv;   //BRR寄存器应赋的值

   

    //变量赋值

   

    RCC_APB1=0x40021058UL;   //UART时钟使能寄存器地址

    RCC_AHB2=0x4002104CUL;   //GPIO的A口时钟使能寄存器地址

    gpio_ptr=0x48000000UL;   //GPIOA端口的基地址

    uart_ptr=0x40004400UL;  //UART2端口的基地址

    gpio_mode=0x48000000UL;    //引脚模式寄存器地址=口基地址

    gpio_afrl=0x48000020UL;    // GPIO复用功能低位寄存器

    uart_cr1=0x40004400UL;       //UART控制寄存器1基地址

    uart_brr=0x4000440CUL;          // UART波特率寄存器地址

    uart_isr=0x4000441CUL;         // UART中断和状态寄存器基地址

    uart_tdr=0x40004428UL;         //UART发送数据寄存器

    uart_rdr=0x40004424UL;         //UART接收数据寄存器

    uart_cr2=0x40004404UL;      // UART控制寄存器2基地址

    uart_cr3=0x40004408UL;      //UART控制寄存器3基地址

   

    //(1.2)【不变】关总中断

    DISABLE_INTERRUPTS;

   

    //(1.3)给主函数使用的局部变量赋初值

    mMainLoopCount=0;

    //(1.4)给全局变量赋初值

   

    //(1.5)用户外设模块初始化

    gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF);   //初始化蓝灯

        gpio_init(LIGHT_GREEN,GPIO_OUTPUT,LIGHT_OFF); //初始化绿灯

        gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF);     //初始化红灯

    //uart_init(UART_User,115200);

   

    //使能GPIOA和UART2的时钟

    *RCC_APB1|=(0x1UL<<17U);       //UART2时钟使能

    *RCC_AHB2 |=(0x1UL<<0U);       //GPIOA时钟使能

   

    //将GPIO端口设置为复用功能

    //首先将D7、D6、D5、D4清零

    *gpio_mode &= ~((0x3UL<<4U)|(0x3UL<<6U));

    //然后将D7、D6、D5、D4设为1010,设置PTA2、PTA3为复用功能串行功能。

    *gpio_mode |=((0x2UL<<4U)|(0x2UL<<6U));

   

    //选择引脚的端口复用功能

    //首先将D15~D8清零

    *gpio_afrl &= ~((0xFUL<<8U)|(0xFUL<<12U));

    //然后将D15~D8设置为01110111,分别将PTA3、PTA2引脚设置为USART2_RX、USART2_TX

    *gpio_afrl=(((0x1UL<<8U)|(0x2UL<<8U)|(0x4UL<<8U))|((0x1UL<<12U)

    |(0x2UL<<12U)|(0x4UL<<12U)));        

   

    //暂时禁用UART功能,控制寄存器1的第0位对应的是UE—USART使能位。

    //此位清零后,USART预分频器和输出将立即停止,并丢弃所有当前操作。

    *uart_cr1 &= ~(0x1UL);

   

    //暂时关闭串口发送与接收功能,控制寄存器1的发送器使能位(D3)、接收器使能位(D2)

    *uart_cr1 &= ~((0x1UL<<3U)|(0x1UL<<2U));

   

    //配置波特率

    if(*uart_cr1&(0x1UL<<15) == (0x1UL<<15))            

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

    else

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

    *uart_brr = usartdiv;

   

    //初始化控制寄存器和中断状态寄存器、清标志位

    //关中断

    *uart_isr = 0x0UL;   

    //将控制寄存器2的两个使能位清零。D14—LIN模式使能位、D11—时钟使能位

    *uart_cr2 &= ~((0x1UL<<14U)|(0x1UL<<11U));

    //将控制寄存器3的三个使能位清零。D5 (SCEN) —smartcard模式使能位、

    //D3 (HDSEL) —半双工选择位、D1 (IREN) —IrDA 模式使能位

    *uart_cr3 &= ~((0x1UL<<5U) | (0x1UL<<3U) |(0x1UL<<1U));

   

    //启动串口发送与接收功能

    *uart_cr1 |= ((0x1UL<<3U)|(0x1UL<<2U));

   

    //开启UART功能

    *uart_cr1 |= (0x1UL<<0U);

   

    //(1.6)使能模块中断

    uart_enable_re_int(UART_User);  //使能UART_User模块接收中断功能

    //(1.7)【不变】开总中断

    ENABLE_INTERRUPTS;

   

   

   

for(;;)

{

    // 判断接收缓冲区是否满,接受字符

     if (*uart_isr & (0x1UL << 5U)) {

        // 读取接收到的字符

        ch = (uint8_t)(*uart_rdr & 0xFF);

        //接收到字符时的处理

        switch (ch) {

            case 'G':

                gpio_set(LIGHT_RED, LIGHT_OFF);    // 关闭红灯

                gpio_set(LIGHT_BLUE, LIGHT_OFF);   // 关闭蓝灯

                gpio_set(LIGHT_GREEN, LIGHT_ON);  // 亮绿灯

                break;

            case 'R':

                gpio_set(LIGHT_GREEN, LIGHT_OFF);  // 关闭绿灯

                gpio_set(LIGHT_BLUE, LIGHT_OFF);   // 关闭蓝灯

                gpio_set(LIGHT_RED, LIGHT_ON);    // 亮红灯

                break;

            case 'B':

                gpio_set(LIGHT_RED, LIGHT_OFF);    // 关闭红灯

                gpio_set(LIGHT_GREEN, LIGHT_OFF);  // 关闭绿灯

                gpio_set(LIGHT_BLUE, LIGHT_ON);   // 亮蓝灯

                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);

            

        }

}

   

  

(1)

(2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值