嵌入式系统基础与实践实验报告

班    级     计科223          

姓    名     孙傲            

学    号     2130110259     

指导教师     卢春红              

设计时间     2025/1/1              

  2024    ——    2025   学年第  一  学期

傲哥小记:

孙某自习嵌入式技术,初涉其门,茫然若失。然渐入佳境,方觉其奥妙无穷,乐此不疲。此道既深且广,涵盖硬件与软件之精髓,融汇调试与优化之巧,实为工艺之高也。每一实验,犹若修身齐家,细致入微;每一编程,犹如治国理政,层层递进。是以,我溺此道之中,得以悟其妙理,深感收获颇丰,今愿以笔述其所学,以明其心。

始也,若以为嵌入式不过是机巧之术,殊不知其蕴藏诸多精深之理。串口通信,乃此术之基也。余初学时,未尝知何为“RDR寄存器”,何为“中断接收”。及至操作,始知此法之妙,犹如精工巧匠,精细调控每一丝每一毫。数据字节传送,瞬息之间,指令送达,回音复返。每一次的字符传输,仿佛有丝线相连,机电之间互通有无,心领神会。控制之灯如流水般起伏,彼时彼刻,何其畅快!

至于定时器与中断,亦为此道之大要。定时器者,犹如掌中之钟,分秒必争。利其调度,度之节奏,如指挥大军行进,精准有序。余用定时器现三色灯依时交替。时光流转,光辉变换,仿佛与天同步,顺应四时之律。此之操作,使我深感时空之流动,机器之默契。

而PWM控制,乃为心灯之技也。此法似能使光亮之强弱,随意调控,如同掌控心境之起伏。通过数字0至100,操控占空比控LED光亮强度,仿佛成了光的主宰。每一微小变化,直接感知,犹如调节内心澄明昏暗,尽在掌控之间。

更有实时操作系统(RTOS)中之线程管理,令我如见帝王之权谋,众事齐行,各有其时,井然有序。流水灯之效果,正是通过线程交替实现,犹如庙堂之高,权力之分配,微妙且灵活。每一任务,各司其职,互不干扰,恰如大明宫中权臣与国君,精妙协作,运转如常。

Flash存储与数据持久化操作,亦让我得以深悟“存与取”之道。通过串口操作,数据之写入与读取,犹如春秋之藏,固守智慧与经历。时间数据写入,并在每次开机时自动展示,犹如记忆之门,开启时刻,往事历历在目。余在此道上,领略了数据存储与提取之奥义,再现数据库与图片存储之大能,方知科技亦可承载历史与智慧,纵使时光荏苒,信息亦能历久弥新。

此等诸般技术,均是嵌入式之精髓,兼顾软件硬件之默契,正是技术之艺术。每一次代码之敲定,灯光之辉,乃是心机与智慧结晶。此道机械的操控,更为智慧的呈现与灵魂的表达。嵌入式之学,教我如何与世界对话,如何让机器理解人类的意图;如何在有限的硬件资源下,实现无限的创意与梦想。

余今得此,深感荣幸,未来当更加精进,欲在此道上求得真知,通达其理,化繁为简,使机械更懂人心。

第七周:

实验目的与要求:
1、增加利用RDR寄存器接收一个字节并回送至PC功能(直接地址法);
2、修改初始化函数的相关寄存器:数据帧:7(数据位)+2/1(停止位),波特率:9600,利用PC软件测试收发(直接地址法)
3、参考MCU 串口中断样例程序,利用该程序框架实现:通过串口调试工具,PC 机发送字符‘1’或者‘0’来控制开发板上三色灯,MCU 的接收到字符‘1’时打开灯,接收到字符‘0’时关闭灯
4、参考MCU 串口中断样例程序,利用该程序框架实现:通过串口调试工具,PC 机发送字符‘1’或者‘0’来控制一个LED灯,MCU 的接收到字符‘1’时打开LED灯,接收到字符‘0’时关闭LED灯(自己外接LED灯)。
5、参考MCU 串口中断样例程序,,结合之前流水灯实验,实现串口 发送数字1、2、3、4控制四种流水灯
6、参考MCU 串口中断样例程序,利用该程序框架实现:通过串口调试工具,PC 机发送字符串“Open”或者“Close” 来控制开发板上三色灯中的一个LED 灯,MCU 的接收到字符串“Open”时打开LED 灯,接收到字符串“Close”时关闭LED 灯。参考组帧程序编写

实验过程与数据记录:

1. uint8_t uart_re1(uint8_t uartNo,uint8_t *fp)

{

    uint32_t t;

    uint8_t  dat;

    //判断传入串口号参数是否有误,有误直接退出

       if(!uart_is_uartNo(uartNo)) return 0;

       //判断传入串口号参数是否有误,有误直接退出

       if(!uart_is_uartNo(uartNo))

       {

              *fp=0;

              return 0;

       }

       for (t = 0; t < 0xFBBB; t++)//查询指定次数

       {

              //判断接收缓冲区是否满

              if (USART_ARR[uartNo-1]->ISR & USART_ISR_RXNE_Msk)

              {

                     dat=USART_ARR[uartNo-1]->RDR;    //获取数据,清接收中断位

                     *fp = 1;  //接收成功

                     break;

              }

       }//end for

       if(t >= 0xFBBB)

       {

              dat = 0xFF;

              *fp = 0;    //未收到数据

       }

       return dat;    //返回接收到的数据

}

使用方法也很简单,received_data = uart_re1(uart, &result_flag);可以实现接收串口发送的数据。

2. uint8_t uart_send1(uint8_t uartNo, uint8_t ch)

{   uint32_t t;

       //判断传入串口号参数是否有误,有误直接退出

       if(!uart_is_uartNo(uartNo)) return 0;

       for (t = 0; t < 0xFBBB; t++)//查询指定次数

       {

              //发送缓冲区为空则发送数据

              if ( USART_ARR[uartNo-1]->ISR & USART_ISR_TXE_Msk )

              {

                     USART_ARR[uartNo-1]->TDR = ch;

                     break;

              }

       }//end for

       if (t >= 0xFBBB)

              return 0; //发送超时,发送失败

       else

              return 1; //成功发送

}

可以通过uart_send1(uartNo, str);来实现数据的回发

uart_init(UART_User,9600);可以用来初始化串口

//发送“数字48~100”

        for (mi=0;mi<=255;mi++)

        {

          uart_send1(UART_User,mi);

        }

        uart_send_string(UART_User,(uint8_t *)"---");

可以看到这个是实现发送0到255数据的示例

3.   uint8_t sun;

    uint8_t receivedData; // 接收到的数据

uint8_t ledState = LIGHT_OFF; // 红灯状态变量(初始为关闭)

    receivedData = uart_re1(UART_User, &sun);

        // 根据接收到的数据控制红灯

        if (receivedData == 1 && ledState == LIGHT_OFF) {

            gpio_set(LIGHT_RED, LIGHT_ON);

            ledState = LIGHT_ON; // 更新红灯状态

        } else if (receivedData == 0 && ledState == LIGHT_ON) {

            gpio_set(LIGHT_RED, LIGHT_OFF);

            ledState = LIGHT_OFF; // 更新红灯状态

        }

这个关键的部分是用来实现判断接收到1实现板子三色灯亮,接收到0实现板子三色灯灭的关键代码。

4.

#define  LIGHT1    (PTA_NUM|8)

#define  LIGHT2    (PTB_NUM|11)

receivedData = uart_re1(UART_User, &sun);

        // 根据接收到的数据控制红灯

        if (receivedData == 1 && ledState == LIGHT_OFF) {

            gpio_set(LIGHT1, LIGHT_ON);

            ledState = LIGHT_ON; // 更新红灯状态

        } else if (receivedData == 0 && ledState == LIGHT_ON) {

            gpio_set(LIGHT1, LIGHT_OFF);

            ledState = LIGHT_OFF; // 更新红灯状态

        }

这个关键的部分是用来实现判断接收到1实现板子外接灯亮,接收到0实现板子外接灯灭的关键代码。

5.

receivedData = uart_re1(UART_User, &sun);

        // 根据接收到的数据控制红灯

        if (receivedData == 1 && ledState == 1) {

            gpio_set(LIGHT_RED, LIGHT_ON);

            gpio_set(LIGHT_BLUE, LIGHT_OFF);

            gpio_set(LIGHT_GREEN, LIGHT_OFF);

            ledState = 2; // 更新红灯状态

            printf("红灯:亮\n");

        } else if (receivedData == 2 && ledState == 2) {

            gpio_set(LIGHT_RED, LIGHT_OFF);

            gpio_set(LIGHT_BLUE, LIGHT_ON);

            gpio_set(LIGHT_GREEN, LIGHT_OFF);

            ledState = 3; // 更新红灯状态

            printf("蓝灯:亮\n");

        } else if (receivedData == 3 && ledState == 3) {

            gpio_set(LIGHT_RED, LIGHT_OFF);

            gpio_set(LIGHT_BLUE, LIGHT_OFF);

            gpio_set(LIGHT_GREEN, LIGHT_ON);

            ledState = 4; // 更新红灯状态

            printf("绿灯:亮\n");

        } else if (receivedData == 4 && ledState == 4) {

            gpio_set(LIGHT_RED, LIGHT_ON);

            gpio_set(LIGHT_BLUE, LIGHT_OFF);

            gpio_set(LIGHT_GREEN, LIGHT_ON);

            ledState = 1; // 更新红灯状态

            printf("黄灯:亮\n");

        }

这段代码可以用于一个类似交通信号灯控制系统的场景,在该场景中,串口通信用来接收指令来控制不同颜色的 LED 灯。接收到的不同指令(1, 2, 3, 4)代表不同的灯状态,并且可以根据当前状态进行灯光的切换。

6.组帧函数如下

#define FrameHead    (0x50)       //帧头     ASCII码对应P

#define FrameTail    (0x43)       //帧尾     ASCII码对应C

//P4openC

uint8_t CreateFrame(uint8_t Data,uint8_t * buffer)

{

    static uint8_t frameLen=0;    //帧的计数器

    uint8_t frameFlag;            //组帧状态

    frameFlag=0;            //组帧状态初始化

    //根据静态变量frameCount组帧

    switch(frameLen)

    {

        case 0:    //第一个数据

        {

            if (Data==FrameHead)    //收到数据是帧头FrameHead

            {

                buffer[0]=Data;

                frameLen++;

                frameFlag=0;        //组帧开始

            }

            break;

        }

        case 1:    //第二个数据,该数据是随后接收的数据个数

        {

            buffer[1]=Data-0x30;

            frameLen++;

            break;

        }

        default:    //其他情况

        {

            //第二位数据是有效数据长度,根据它接收余下的数据直到帧尾前一位

            if(frameLen>=2 && frameLen<=(buffer[1] + 1))

            {

                buffer[frameLen]=Data;

                frameLen++;

                break;

            }

            //若是末尾数据则执行

            if(frameLen>=(buffer[1]+2))

            {

                if (Data==FrameTail)    //若是帧尾

                {

                    buffer[frameLen]=Data;     //将帧尾存入缓冲区

                    frameFlag=1;    //组帧成功

                }

                frameLen=0    ;     //计数清0,准备重新组帧

                break;

            }

        }

    }     //switch_END

    return frameFlag;                 //返回组帧状态

}

这个函数实现了一个简单的帧解析机制,用于接收和组装一个特定格式的数据帧。

数据帧的格式由帧头、数据长度、有效数据和帧尾组成。

CreateFrame 函数通过逐字节接收数据并根据帧格式进行处理,最后返回帧是否组装成功的标志。

在嵌入式系统中,DISABLE_INTERRUPTS 和 ENABLE_INTERRUPTS 是用于控制中断使能的宏,它们的作用是在执行某些关键操作时禁用和启用中断,以保证操作的原子性和防止中断干扰。

void UART_User_Handler(void) {

    uint8_t ch, flag;

    DISABLE_INTERRUPTS;  // 关总中断

    ch = uart_re1(UART_User, &flag);  // 接收一个字节

    // 调用内部函数CreateFrame进行组帧

    if (CreateFrame(ch, g_uart_recvBuf) != 0) {  // 组帧成功

        // 如果收到“Open”命令

        if (strncmp((const char*)&g_uart_recvBuf[2], "Open", 4) == 0) {

            gpio_set(LIGHT_BLUE, LIGHT_ON);  // 打开LED灯

            uart_send1(UART_User,ch);

        }

        // 如果收到“Close”命令

        else if (strncmp((const char*)&g_uart_recvBuf[2], "Close", 5) == 0) {

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

            uart_send1(UART_User,ch);

        }

        // 其他命令的处理(如果需要)

    }

    ENABLE_INTERRUPTS;  // 开总中断

}

UART_User_Handler 函数的流程:

关中断 (DISABLE_INTERRUPTS),确保函数执行过程不被打断。

接收数据:调用 uart_re1 函数接收一个字节的数据,并根据接收到的数据进行帧的组装。

解析命令

如果接收到的数据帧中包含 "Open" 命令,则打开蓝色 LED 灯。

如果接收到的数据帧中包含 "Close" 命令,则关闭蓝色 LED 灯。

响应数据:根据命令,向串口发送响应数据。

开中断 (ENABLE_INTERRUPTS),允许中断响应系统的其他事件

 

第八周:

实验目的与要求:
1. 利用组帧方法完成C#方和MCU方程序功能,C#方程序实现鼠标单击相应按钮,控制开发板上的三色灯完成“红、绿、蓝、青、紫、黄、白、暗”显示的控制。
2. 修改流水灯实验,通过systick定时器实现延时
3. 用systick模块,实现蓝灯亮2秒,红灯亮4秒,绿灯亮6秒的交替循环变化
4. 自行编写上位机软件,通过串口设置定时器初始计时时间,(也可以自动获取系统时间)

实验过程与数据记录:

1.

金葫芦里中断函数

void UART_User_Handler(void) {

    uint8_t ch, flag;

    DISABLE_INTERRUPTS;  // 关总中断

    ch = uart_re1(UART_User, &flag);  // 接收一个字节

    // 调用内部函数CreateFrame进行组帧

    if (CreateFrame(ch, g_uart_recvBuf) != 0) {  // 组帧成功

        // 如果收到“Open”命令

        if (strncmp((const char*)&g_uart_recvBuf[2], "open1", 5) == 0) {

            gpio_set(LIGHT_BLUE, LIGHT_OFF);  // 打开LED灯

            gpio_set(LIGHT_GREEN, LIGHT_OFF);

            gpio_set(LIGHT_RED, LIGHT_ON);

            uart_send1(UART_User,ch);

        }

        // 如果收到“Close”命令

        else if (strncmp((const char*)&g_uart_recvBuf[2], "open2", 5) == 0) {

            gpio_set(LIGHT_BLUE, LIGHT_ON);  // 关闭LED灯

            gpio_set(LIGHT_GREEN, LIGHT_OFF);

            gpio_set(LIGHT_RED, LIGHT_OFF);

            uart_send1(UART_User,ch);

        }

        else if (strncmp((const char*)&g_uart_recvBuf[2], "open3", 5) == 0) {

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

            gpio_set(LIGHT_GREEN, LIGHT_ON);

            gpio_set(LIGHT_RED, LIGHT_OFF);

            uart_send1(UART_User,ch);

        }

        else if (strncmp((const char*)&g_uart_recvBuf[2], "open4", 5) == 0) {

            gpio_set(LIGHT_BLUE, LIGHT_ON);  // 关闭LED灯

            gpio_set(LIGHT_GREEN, LIGHT_ON);

            gpio_set(LIGHT_RED, LIGHT_OFF);

            uart_send1(UART_User,ch);

        }

        else if (strncmp((const char*)&g_uart_recvBuf[2], "open5", 5) == 0) {

            gpio_set(LIGHT_BLUE, LIGHT_ON);  // 关闭LED灯

            gpio_set(LIGHT_GREEN, LIGHT_OFF);

            gpio_set(LIGHT_RED, LIGHT_ON);

            uart_send1(UART_User,ch);

        }

        else if (strncmp((const char*)&g_uart_recvBuf[2], "open6", 5) == 0) {

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

            gpio_set(LIGHT_GREEN, LIGHT_ON);

            gpio_set(LIGHT_RED, LIGHT_ON);

            uart_send1(UART_User,ch);

        }

        else if (strncmp((const char*)&g_uart_recvBuf[2], "open7", 5) == 0) {

            gpio_set(LIGHT_BLUE, LIGHT_ON);  // 关闭LED灯

            gpio_set(LIGHT_GREEN, LIGHT_ON);

            gpio_set(LIGHT_RED, LIGHT_ON);

            uart_send1(UART_User,ch);

        }

        else if (strncmp((const char*)&g_uart_recvBuf[2], "close", 5) == 0) {

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

            gpio_set(LIGHT_GREEN, LIGHT_OFF);

            gpio_set(LIGHT_RED, LIGHT_OFF);

            uart_send1(UART_User,ch);

        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值