第六章作业

作业一:

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

(1)确定MCU串口号、所接MCU的引脚;采用的串口为UART_2(编程默认使用UART_User)

(2)确定串口UART_User的波特率,并对其进行初始化

(3)调用uart_send1接口函数发送数据

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

有两种情况:

当USART_CR1中的第15位的过采样模式为0,则结果为625;

当USART_CR1中的第15位的过采样模式为1,则结果为1250;

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

在CH06中的UART-STM21L431-ISR-20210109中的03_MCU中startup里的startup_stm321I431lrctx.s文件中;

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

TIM6中断的IRQ号为54;

(((uint32_t)IRQn) >> 5UL)=1;

1UL << (((uint32_t)IRQn) & 0x1FUL)操作为将1左移IRQ号对应前5位的值,结果为22;

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

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

交换后,UART_2 的中断号变为 54,TIM6 的中断号变为 38,这种情况下,只要在代码中修改正确配置新的中断向量和IRQ号,UART_2就正常中断;TIM6同理只需要重新修改成正确的终端向量和IRQ号就可以正常中断。因为中断号的交换并不影响中断控制器 NVIC 中的配置,只是改变了中断向量表中的中断函数入口地址。

作业二:

 

1、用构件调用方式实现

代码:

//======================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:20191108-20201106
//功能描述:见本工程的..\01_Doc\Readme.txt
//移植规则:【固定】
//======================================================================
#define GLOBLE_VAR
#include "includes.h"      //包含总头文件


//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处

//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
//(1)======启动部分(开头)==========================================
//(1.1)声明main函数使用的局部变量
    uint32_t mMainLoopCount;  //主循环次数变量
    uint8_t  mFlag;           //灯的状态标志
    uint8_t  mTest;

//(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(;;)(开头)
    {
//(2.1)主循环次数变量+1
        mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
        if (mMainLoopCount<=3000000)  continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
        mMainLoopCount=0; 
//(2.3.2)通过调试串口提示
        printf("金葫芦友情提示:\r\n");
       // printf("蓝灯亮暗次数=%d,  关闭本窗体\r\n",mLightCount);
        printf("“工具”→“串口工具”,打开接收User串口数据观察\r\n");
        mFlag=uart_re1(UART_User,&mTest);
//(2.3.3)若接收到字符mTest为1,未接收到则为0

        if(mTest)
        {
            uart_send1(UART_User,mFlag+1);
            if(mFlag == 'G')
            {
                gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯
                gpio_set(LIGHT_BLUE,LIGHT_OFF);  // 关闭蓝灯
                gpio_set(LIGHT_GREEN,LIGHT_ON);  //亮绿灯
            }
            else if(mFlag == 'B')
            {
                gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯
                gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
                gpio_set(LIGHT_BLUE,LIGHT_ON);   // 亮蓝灯
            }
            else if(mFlag == 'R')
            {    
                gpio_set(LIGHT_GREEN,LIGHT_OFF);  // 关闭绿灯
                gpio_set(LIGHT_BLUE,LIGHT_OFF);   // 关闭蓝灯
                gpio_set(LIGHT_RED,LIGHT_ON);     // 亮红灯
            }
            else
            {    
                gpio_set(LIGHT_RED,LIGHT_OFF);   // 关闭红灯
                gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
                gpio_set(LIGHT_BLUE,LIGHT_OFF);  // 关闭蓝灯
            }
        }
    }  //for(;;)结尾
    

//(2)======主循环部分(结尾)========================================

}   //main函数(结尾)


//======以下为主函数调用的子函数===========================================

//*void USART_Test(){

//}*/
 
//=========================================================================
/*
 知识要素:
 (1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
      实现对硬件的干预。
 (2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
      义全局变量,在其他文件中包含"includes.h"头文件时,
      编译时会自动增加extern
 */
 

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

//======================================================================
//文件名称:main.c(应用工程主函数)
//框架提供:SD-Arm(sumcu.suda.edu.cn)
//版本更新:20191108-20201106
//功能描述:见本工程的..\01_Doc\Readme.txt
//移植规则:【固定】
//======================================================================
#define GLOBLE_VAR
#include "includes.h"      //包含总头文件


//----------------------------------------------------------------------
//声明使用到的内部函数
//main.c使用的内部函数声明处

//----------------------------------------------------------------------
//主函数,一般情况下可以认为程序从此开始运行(实际上有启动过程,参见书稿)
int main(void)
{
    //(1)======启动部分(开头)==========================================
    //(1.1)声明main函数使用的局部变量
    uint8_t  mTest;
    uint32_t mCount;
    uint8_t  mFlag;
    
    //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)给主函数使用的局部变量赋初值
    mCount=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;
    
    
    //(1)======启动部分(结尾)==========================================
    
    //(2)======主循环部分(开头)========================================
    
    for(;;)
    {
        if(*uart_isr & (0x1UL << 5U))
        {
            mFlag = (uint8_t)(*uart_tdr & 0xFF);
            //发送缓冲区为空则发送数据
            if(mFlag=='G')
            {
                gpio_set(LIGHT_RED,LIGHT_OFF);  // 关闭红灯
                gpio_set(LIGHT_BLUE,LIGHT_OFF); // 关闭蓝灯
                gpio_set(LIGHT_GREEN,LIGHT_ON); //亮绿灯
            }
            else if(mFlag == 'B')
            {
                gpio_set(LIGHT_RED,LIGHT_OFF);  // 关闭红灯
                gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
                gpio_set(LIGHT_BLUE,LIGHT_ON);  // 亮蓝灯
            }
            else if(mFlag == 'R')
            {
                gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
                gpio_set(LIGHT_BLUE,LIGHT_OFF);  // 关闭蓝灯
                gpio_set(LIGHT_RED,LIGHT_ON);  // 亮红灯
            }
            else
            {
                gpio_set(LIGHT_RED,LIGHT_OFF);  // 关闭红灯
                gpio_set(LIGHT_GREEN,LIGHT_OFF); // 关闭绿灯
                gpio_set(LIGHT_BLUE,LIGHT_OFF); // 关闭蓝灯
            }
            printf("%c\n",mFlag+1);
        }
    }  
    //(2)======主循环部分(结尾)========================================
    
}   //main函数(结尾)


//======以下为主函数调用的子函数===========================================

//*void USART_Test(){
    
    //}*/
    
    //=========================================================================
    /*
    知识要素:
    (1)main.c是一个模板,该文件所有代码均不涉及具体的硬件和环境,通过调用构件
    实现对硬件的干预。
    (2)本文件中对宏GLOBLE_VAR进行了定义,所以在包含"includes.h"头文件时,会定
    义全局变量,在其他文件中包含"includes.h"头文件时,
    编译时会自动增加extern
    */
    
    
    
    
    
    
    
    
    
    
 

  • 31
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值