嵌入式作业五

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

初始化需要设置的参数主要有:

  • 波特率(Baud rate):波特率是指串口通信中每秒钟传输的比特数,它决定了数据传输的速率,在初始化时需要设置一个与通信双方协商好的波特率,确保数据的传输速率一致,以避免数据丢失或错误。

  • 数据位(Data bits):数据位指每个数据字节中实际的数据位数,常见的数据位包括8位、7位或者其他,初始化时需要设置数据位,以确保发送和接收的数据字节格式一致。

  • 停止位(Stop bits):停止位是在每个数据字节传输结束时发送的特殊位,用于告知接收端一个数据字节的传输已经完成,通常为1位或2位。初始化时需要设置停止位,以确保数据传输的可靠性和准确性。

  • 校验位(Parity bits):校验位是一种用于检测数据传输过程中错误的方法。在串口通信中,可以选择是否使用校验位,并选择奇偶校验、偶校验或者不使用校验,初始化时需要设置校验位,以确保数据的完整性和正确性。

  • 中断使能(Interrupt Enable):允许触发接收、发送和错误中断,以实现异步数据收发和错误处理。

除此之外一系列UART寄存器也需要进行初始化设置:

时钟使能寄存器地址、端口的基地址寄存器、引脚模式寄存器地址、UART波特率寄存器地址、UART中断和控制寄存器基地址、UART发送/接受寄存器等等。

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

在OVER8 = 1时中波特率寄存器BRR的值应为:

(72MHz/115200) * 2 = 1250

在OVER8 = 0时中波特率寄存器BRR的值为:

(72MHz/115200) = 625

3、中断向量表在哪个文件中?表中有多少项?

中断向量表在stm32l431xx.h文件中,以下是相关中断向量的向量号

表中一共有72项

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

__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
  if ((int32_t)(IRQn) >= 0)
  {
    NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
  }
}

在中断向量表中查看得出TIM6为54

则代入函数中即可得 54>>5UL 可得索引值为1

在1UL<< 54 & 0x1FUL 可得为第22位

即 NVIC->ISER[1]=0000 0000 0100 0000 0000 0000

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

如果只是交换了UART_2和TIM6的IRQ号,而没有交换它们在中断向量表中的位置,那么UART_2仍然可以正常中断:

  1. 当UART_2发生中断事件时,即使IRQ号被错误地链接到了TIM6的中断处理程序,但由于中断向量表中UART_2的位置没有变,它的中断处理函数仍然能被正确调用。

  2. 同样,当TIM6发生中断时,即使IRQ号被错误地链接到了UART_2的中断处理程序,但由于中断向量表中TIM6的位置没有变,它的中断处理函数仍然能被正确调用。

所以在这种情况下,只要中断向量表的映射关系保持正确,UART_2就能够正常响应并处理中断事件。

但如果不仅IRQ号被交换,中断向量表的位置也被交换,那么UART_2就无法正常中断,因为它的中断处理程序将被错误地链接到了TIM6的中断向量。

综上所述, UART_2只有在IRQ号被交换但中断向量表没有被交换的情况下,才能够正常中断。一旦中断向量表的映射关系被错误地交换,UART_2就无法正常工作。

6.运行并理解..\04\-Software\CH06文件夹中的几个程序

在ADDR中代码的含义如下:

主函数开始,首先声明了一些局部变量和指针,然后进行了一系列的初始化设置,包括设置GPIO、UART的时钟使能、引脚复用功能等,初始化完成后,启动主循环部分,其中使用了两个嵌套的for循环。在内部的循环中,通过检查串口的发送缓冲区状态来发送数据,并在外部的循环中不断增加发送次数并打印信息。

在isr代码中:

主要实现了串口工具对于灯亮灭的操作。并且在串口工具中对接收到的信息进行回复。

在Sent代码中:

实现了在一个无限循环中,定时切换蓝色LED的状态,并通过调试串口打印消息,再通过UART发送一系列字符和字符串。

7.实现UART_2串口的接收程序,当收到字符时:

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

②亮灯:收到字符G,亮绿灯;收到字符R,亮红灯;收到字符B,亮蓝灯;收到其他字符,不亮灯。

实现方式:

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

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

(1)用构件方式:

void USART2_IRQHandler(void)
{
    uint8_t ch;
	uint8_t flag;
	DISABLE_INTERRUPTS;   //关总中断
	if(uart_get_re_int(UART_User))
	{
		ch=uart_re1(UART_User,&flag);
		if(flag)
		{
			if(ch=='R')
			{
				gpio_set(LIGHT_GREEN,LIGHT_OFF);
				gpio_set(LIGHT_BLUE,LIGHT_OFF);
				gpio_set(LIGHT_RED,LIGHT_ON);
			}
			else if(ch=='G')
			{
				gpio_set(LIGHT_GREEN,LIGHT_ON);
				gpio_set(LIGHT_BLUE,LIGHT_OFF);
				gpio_set(LIGHT_RED,LIGHT_OFF);
			}
			else if(ch=='B')
			{
				gpio_set(LIGHT_GREEN,LIGHT_OFF);
				gpio_set(LIGHT_RED,LIGHT_OFF);
				gpio_set(LIGHT_BLUE,LIGHT_ON);
			}
			else
			{
				gpio_set(LIGHT_GREEN,LIGHT_OFF);
				gpio_set(LIGHT_BLUE,LIGHT_OFF);
				gpio_set(LIGHT_RED,LIGHT_OFF);
			}
		}
	}
	uart_send1(UART_User,ch+1);
	ENABLE_INTERRUPTS;    //开总中断
}

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

在主函数中添加接收寄存器的定义其他不变
   //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_cr2=0x40004404UL;      // UART控制寄存器2基地址
    uart_cr3=0x40004408UL;      //UART控制寄存器3基地址
uart_rdr=0x40004424UL;         // UART2接收数据寄存器基地址

//(1.2)【不变】关总中断
    DISABLE_INTERRUPTS;
    
    //(1.4)给全局变量赋初值
    
    //(1.5)用户外设模块初始化
    gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_OFF);	//初始化蓝灯
    gpio_init(LIGHT_RED,GPIO_OUTPUT,LIGHT_OFF);
    gpio_init(LIGHT_GREEN,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 (t = 0; t < 0xFBBB; t++)//查询指定次数
	{
		//判断接收缓冲区是否满
		if (*uart_isr & (0x1UL<<5UL))
		{
			ch = *uart_rdr;    //获取数据,清接收中断位
			flag = 1;  //接收成功
			break;
		}
	}
	if(t >= 0xFBBB)
	{
		ch = 0xFF;
		flag = 0;    //未收到数据
	}
        // 检查是否已经接收到数据
        if (flag)
        { 
            // 处理接收到的字符
            switch(ch)
            {
                case 'G':
                    // 关闭其他颜色LED 打开绿色LED
                    gpio_set(LIGHT_RED, LIGHT_OFF);
                    gpio_set(LIGHT_BLUE, LIGHT_OFF);
                    gpio_set(LIGHT_GREEN, LIGHT_ON);
                    break;
                case 'R':
                    // 打开红色LED
                    gpio_set(LIGHT_GREEN, LIGHT_OFF);
                    gpio_set(LIGHT_BLUE, LIGHT_OFF);
                    gpio_set(LIGHT_RED, LIGHT_ON);
                    break;
                case 'B':
                    // 打开蓝色LED
                    gpio_set(LIGHT_GREEN, LIGHT_OFF);
                    gpio_set(LIGHT_RED, LIGHT_OFF);
                    gpio_set(LIGHT_BLUE, LIGHT_ON);
                    break;
                default:
                    // 关闭所有LED
                    gpio_set(LIGHT_GREEN, LIGHT_OFF);
                    gpio_set(LIGHT_RED, LIGHT_OFF);
                    gpio_set(LIGHT_BLUE, LIGHT_OFF);
                    break;
            }
            //发回已接收到的字符
            for (t = 0; t < 0xFBBB; t++)//查询指定次数
		  {
			//发送缓冲区为空则发送数据
			if ( *uart_isr & (0x1UL<<7UL))
			   {
				*uart_tdr = ch+1;
				break;
			  }
		
         }
      }    
} 

在这个实验中,首先运行和理解了..\04-Software\CH06文件夹中的几个程序,通过阅读这些程序的代码,我对嵌入式系统的基本框架、串口通信、GPIO控制和中断处理有了一定的了解。接着编写UART_2串口的接收程序,使用了调用函数的方式来实现UART的初始化和中断设置,并编写了中断处理函数来处理UART接收到的数据。根据接收到的字符,成功实现了控制绿灯、红灯和蓝灯的亮灭,并在电脑的输出窗口显示下一个字符。在实现过程中,我遇到了一些问题,例如理解中断处理函数的编写方法以及如何正确地控制GPIO以点亮和熄灭LED。通过查阅资料和尝试不同的方法,最终成功地解决了这些问题,并且完成了实验要求,在实验结束后,我意识到嵌入式系统开发中对于细节的重视,以及对硬件和软件交互的深入理解的重要性。

总的来说,在本实验中我熟悉了MCU异步通信Uart的工作原理、通信编程方法、中断的使用方法和串口的调试,对于接下来嵌入式编程有了一定的基础知识。

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动控制节水灌溉技术的高低代表着农业现代化的发展状况,灌溉系统自动化水平较低是制约我国高效农业发展的主要原因。本文就此问题研究了单片机控制的滴灌节水灌溉系统,该系统可对不同土壤的湿度进行监控,并按照作物对土壤湿度的要求进行适时、适量灌水,其核心是单片机和PC机构成的控制部分,主要对土壤湿度与灌水量之间的关系、灌溉控制技术及设备系统的硬件、软件编程各个部分进行了深入的研究。 单片机控制部分采用上下位机的形式。下位机硬件部分选用AT89C51单片机为核心,主要由土壤湿度传感器,信号处理电路,显示电路,输出控制电路,故障报警电路等组成,软件选用汇编语言编程。上位机选用586型以上PC机,通过MAX232芯片实现同下位机的电平转换功能,上下位机之间通过串行通信方式进行数据的双向传输,软件选用VB高级编程语言以建立友好的人机界面。系统主要具有以下功能:可在PC机提供的人机对话界面上设置作物要求的土壤湿度相关参数;单片机可将土壤湿度传感器检测到的土壤湿度模拟量转换成数字量,显示于LED显示器上,同时单片机可采用串行通信方式将此湿度值传输到PC机上;PC机通过其内设程序计算出所需的灌水量和灌水时间,且显示于界面上,并将有关的灌水信息反馈给单片机,若需灌水,则单片机系统启动鸣音报警,发出灌水信号,并经放大驱动设备,开启电磁阀进行倒计时定时灌水,若不需灌水,即PC机上显示的灌水量和灌水时间均为0,系统不进行灌水。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值