实验二 串口通信及中断实验

2023-05-16

一.实验目的

(1)熟悉 MCU 的异步串行通信 Uart 的工作原理。

(2)掌握 Uart 的通信编程方法。

(3)掌握中断的编程方法。

(4)掌握 PC 机的 C#串口通信编程方法。

二.实验内容

1.验证性实验

在光盘资料中 SD-KL-CD 提供读者串口通信实例 ch06-UART 文件夹中的 UART 程序主要实现开发板上的蓝灯闪烁、通过 MCU 串口发送字符串"change light"、回发接收数据。将光盘中的UART 程序下载至目标板,将USB转TTL串口线连接至开发板和电脑的USB口,打开串口调试工具或 ch06-UART 文件夹中的“C#2010 串口测试程序”进行串口通信测试,理解 main.c 程序和中断服务例程 isr.c。PC 机的 C#界面设计了发送文本框和接收字符型文本框、十进制型文本框、十六进制型文本框,理解接收、发送功能。

2.设计性实验

(1)修改光盘资料中 SD-KL-CD 提供读者串口通信实例 ch06-UART 文件夹中的 UART程序,实现通过串口调试工具或 ch06-UART 文件夹中的“C#2010 串口测试程序”发送字符’1’或者’0’来控制开发板上的蓝色 LED 灯,MCU 的 UART 接收到字符’1’时打开蓝色 LED灯,接收到字符’0’ 时关闭蓝色 LED 灯。

请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句。

(2)修改光盘资料中 SD-KL-CD 提供读者串口通信实例 ch06-UART 文件夹中的 UART程序,实现通过串口调试工具或 ch06-UART 文件夹中的“C#2010 串口测试程序”发送字符串’open’或者’close’来控制开发板上的蓝色 LED 灯,MCU 的 UART 接收到字符串’open’时打开蓝色 LED 灯,接收到字符串’ close’时关闭蓝色 LED 灯。

请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句。

3.进阶实验★

(1)利用光盘资料中 SD-KL-CD 提供读者串口通信实例 ch06-UART 文件夹中的 UART程序及其“C#2010 串口测试程序”,修改编写 MCU 方和 C#方程序,利用组帧方法来完成串口任意长度数据的接收和发送。实现 C#程序发送字符串’open’或者’close’来控制开发板上的蓝色 LED 灯,MCU 的 UART 接收到字符串’open’时打开蓝色 LED 灯,接收到字符串’ close’时关闭蓝色 LED 灯。

提示:组帧的双方约定“帧头+数据长度+有效数据+帧尾”为数值帧的格式,帧头和帧尾请自行设定。

请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句和 C#方主要程序段。

(2)利用上述实验中的组帧程序完成 C#方和 MCU 方程序功能,C#方程序实现鼠标点击不同按钮对应控制开发板上的三色灯完成相应颜色 LED 灯的显示。

请在实验报告中给出 MCU 端程序 main.c 和 isr.c 流程图及程序语句和 C#方主要程序段。

三.实验步骤和结果

1.验证性实验

将UART程序下载至目标板之后,蓝色小灯在闪烁,同时串口调试助手上接收到以下字符串:

 

经过对代码的分析可知第一行输出是程序通过串口2发送到串口的,其代码为:

uart_init(UART_2, 9600);    //初始化串口2,波特率为9600;

uart_send_string(UART_2, "使用uart_send_string发送:Hello Uart_2!\r\n");

第二行及后续输出是由printf函数发送到串口的,由于printf函数内部将此函数所使用的串口号预先设置为串口2,所以在目标板连接串口2时可以接收到该输出。具体代码如下:

printf("使用printf函数发送:Hello Uart_2!\r\n");

printf("灯状态变换次数mLight_chang_num=%d\n",mLight_chang_num);

预先设置串口号的代码如下(printf内部):


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

2.设计性实验

(1)通过串口输入1或0来控制蓝灯亮暗

思路分析:

  1. 通过串口调试工具向串口发送控制信号:1-小灯亮;0-小灯暗
  2. 注意:黑接GND,绿接RX,白接TX。
  3. 串口中断(UART2)接收到之后进行处理,判断,如果接收到的字符为’1’,则控制小灯亮,如果接收到的字符为’0’,则控制小灯暗

流程图(由于控制小灯亮暗的程序写在了串口中断函数中,故只写串口流程图,下同):

具体代码如下:

 

实验现象:

同要求一致。

(2)输入’open’和’close’来控制小灯的亮暗

思路分析:

  1. 本实验同前一个实验要求基本一直,故可将原实验中对1和0的判断改为对open和close的判断。我在这里使用了组帧的方式进行指令的发送。
  2. 组帧分析:第一位为帧头P 最后一位为帧尾C 第二位为发送数据的位数。

举例:发送open指令:P4openC ;发送close指令:P5closeC

  1. 首先向串口发送指令
  2. 如果数据部分为open则小灯亮;如果数据部分为close则小灯暗。
  3. 串口获取指令后,从buffer[2]开始,判断buffer[1]位数据。

流程图:

 

具体代码如下:

组帧程序:

//===========================================================================

//ISR名称:Createbuffer

//功能概要:组建数据帧,将待组帧数据加入到数据帧中

//参数说明:Data:         待组帧数据

//          buffer:        数据帧变量

//函数返回:组帧状态    0-组帧未成功,1-组帧成功

//备注:十六进制数据帧格式

//             帧头         + 数据长度 + 有效数据    +     帧尾

//            FrameHead +     len     + 有效数据    + FrameTail

//===========================================================================

uint8_t CreateFrame(uint8_t Data, uint8_t * buffer) {

static uint8_t frameCount = 0;    //组帧计数器

uint8_t frameFlag;              //组帧状态



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

//根据静态变量frameCount组帧

switch (frameCount) {

case 0:    //第一个数据

{

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

{

buffer[0] = Data;

frameCount++;

frameFlag = 0;        //组帧开始

}

break;

}

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

{

buffer[1] = Data - '0';

frameCount++;

break;

}

default:    //其他情况

{

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

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

buffer[frameCount] = Data;

frameCount++;

break;

}

//若是末尾数据则执行

if (frameCount >= (buffer[1] + 2)) {

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

{

buffer[frameCount] = Data;     //将帧尾0x44存入缓冲区

frameFlag = 1;    //组帧成功

}

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

break;

}

}

}     //switch_END

return frameFlag;                 //返回组帧状态

}

串口中断程序:

 

实验现象:

同要求一致。

3.进阶实验★

(1)使用组帧方式发送open和close控制小灯亮暗

由于设计实验的第二次实验已经使用open和close的组帧方式控制小灯亮暗,故不再赘述。

(2)利用组帧方式,在C#设计界面,用图形化的界面控制各种颜色小灯的亮暗。

思路分析:

  1. 在C#程序FormSCI上添加几个按钮,在每个按钮的响应事件中填写控制不同颜色小灯亮暗的程序
  2. 在对应颜色的按钮的响应事件中,将控制改颜色的编码用组帧的方式发送到串口
  3. 串口接收到之后,获取并比对控制数据,选择不同颜色的小灯进行操作。

流程图:

串口中断程序流程:

 

主函数控制流程:

 

C#界面设计:

 

具体代码如下:

C#各按钮响应事件实现程序:

//控制蓝灯

    private void button1_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P4blueC";

            BtnSCISend_Click(sender, e);

        }

        //控制红灯

        private void button2_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P3redC";

            BtnSCISend_Click(sender, e);

        }

        //控制绿灯

        private void button3_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P5greenC";

            BtnSCISend_Click(sender, e);

        }

        //控制黄灯

        private void button4_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P6yellowC";

            BtnSCISend_Click(sender, e);

        }

        //控制青色灯

        private void button5_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P6ngreenC";

            BtnSCISend_Click(sender, e);

        }

        //控制紫色灯

        private void button6_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P6violetC";

            BtnSCISend_Click(sender, e);

        }

        //控制白色灯

        private void button7_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P5whiteC";

            BtnSCISend_Click(sender, e);

        }

        //关灯

        private void button9_Click(object sender, EventArgs e)

        {

            this.TbSCISend.Text = "P5closeC";

            BtnSCISend_Click(sender, e);

        }

串口中断程序:

//串口1接收中断服务例程
void UART1_IRQHandler(void) {

uint_8 ch;

uint_8 flag;

DISABLE_INTERRUPTS;    //关总中断

if (uart_get_re_int(UART_1)) {

ch = uart_re1(UART_1, &flag);    //调用接收一个字节的函数,清接收中断位

if (flag) {

uart_send1(UART_1, ch);     //向原串口发回一个字节

flagFrame = CreateFrame(ch, Buffer);

}

}

ENABLE_INTERRUPTS;

}

主函数控制程序:

if (flagFrame == 1) {//如果组帧成功

if (Buffer[2] == 'b' && Buffer[3] == 'l' && Buffer[4] == 'u'

&& Buffer[5] == 'e') {//蓝灯

light_control(LIGHT_BLUE, LIGHT_ON);

light_control(LIGHT_GREEN, LIGHT_OFF);

light_control(LIGHT_RED, LIGHT_OFF);

} else if (Buffer[2] == 'r' && Buffer[3] == 'e'

&& Buffer[4] == 'd') {//红灯

light_control(LIGHT_RED, LIGHT_ON);

light_control(LIGHT_GREEN, LIGHT_OFF);

light_control(LIGHT_BLUE, LIGHT_OFF);

} else if (Buffer[2] == 'g' && Buffer[3] == 'r' && Buffer[4] == 'e'

&& Buffer[5] == 'e' && Buffer[6] == 'n') {//绿灯

light_control(LIGHT_GREEN, LIGHT_ON);

light_control(LIGHT_BLUE, LIGHT_OFF);

light_control(LIGHT_RED, LIGHT_OFF);

} else if (Buffer[2] == 'y' && Buffer[3] == 'e' && Buffer[4] == 'l'

&& Buffer[5] == 'l' && Buffer[6] == 'o'

&& Buffer[7] == 'w') {//黄灯

light_control(LIGHT_GREEN, LIGHT_ON);

light_control(LIGHT_RED, LIGHT_ON);

light_control(LIGHT_BLUE, LIGHT_OFF);

} else if (Buffer[2] == 'n' && Buffer[3] == 'g' && Buffer[4] == 'r'

&& Buffer[5] == 'e' && Buffer[6] == 'e'

&& Buffer[7] == 'n') {//青灯

light_control(LIGHT_GREEN, LIGHT_ON);

light_control(LIGHT_RED, LIGHT_OFF);

light_control(LIGHT_BLUE, LIGHT_ON);

} else if (Buffer[2] == 'v' && Buffer[3] == 'i' && Buffer[4] == 'o'

&& Buffer[5] == 'l' && Buffer[6] == 'e'

&& Buffer[7] == 't') {//紫灯

light_control(LIGHT_GREEN, LIGHT_OFF);

light_control(LIGHT_RED, LIGHT_ON);

light_control(LIGHT_BLUE, LIGHT_ON);

} else if (Buffer[2] == 'w' && Buffer[3] == 'h' && Buffer[4] == 'i'

&& Buffer[5] == 't' && Buffer[6] == 'e') {//白灯

light_control(LIGHT_GREEN, LIGHT_ON);

light_control(LIGHT_RED, LIGHT_ON);

light_control(LIGHT_BLUE, LIGHT_ON);

} else if (Buffer[2] == 'c' && Buffer[3] == 'l' && Buffer[4] == 'o'

&& Buffer[5] == 's' && Buffer[6] == 'e') {//关灯

light_control(LIGHT_GREEN, LIGHT_OFF);

light_control(LIGHT_RED, LIGHT_OFF);

light_control(LIGHT_BLUE, LIGHT_OFF);

}

}

实验现象:

点击对应按钮,则对应颜色的小灯亮,点击关灯,则小灯暗。

四.实验总结(需加入心得体会)

通过本次实验,我熟悉了MCU异步通信Uart的工作原理、通信编程方法、中断的使用方法以及C#串口通信的方法,在实验的过程中还学到了C#程序的form编程,学会了如何使用和设置按钮。除此之外,我还了解了在传输过程中使用帧格式的重要性,以及对帧格式和组帧、解析方式都学到了很多。

嵌入式技术基础与实践(第4版)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实验二 串口通信及中断实验 的相关文章

随机推荐

  • Morris 遍历

    Morris 遍历 中序遍历 前言 我们在中序遍历的时候 一定先遍历左子树 然后遍历当前节点 最后遍历右子树 在常规方法中 我们用递归回溯或者是栈来保证遍历完左子树可以再回到当前节点 但这需要我们付出额外的空间代价 我们需要用一种巧妙地方法
  • 第九届蓝桥杯c/c++A组省赛题解

    分数 题目 1 1 43 1 2 43 1 4 43 1 8 43 1 16 43 每项是前一项的一半 xff0c 如果一共有20项 求这个和是多少 xff0c 结果用分数表示出来 类似 xff1a 3 2 当然 xff0c 这只是加了前2
  • Ltp介绍及实践(20200925)

    Ltp中源代码和模型包括 xff1a 中文分词 词性标注 未登录词识别 依存句法 语义角色标注几个模块 目录 1 标注集合 分词标注集 词性标注集 命名实体识别标注集 依存句法关系 语义角色类型 2 快速使用 载入模型 分句 用户自定义词典
  • 第十一届蓝桥杯省赛C/C++B组题解

    试题 A 跑步训练 本题总分 xff1a 5 分 题目 问题描述 小明要做一个跑步训练 初始时 xff0c 小明充满体力 xff0c 体力值计为 10000 如果小明跑步 xff0c 每分钟损耗 600 的体力 如果小明休息 xff0c 每
  • codeforces Round680 C. Division 题解

    codeforces Round680 C Division 题解 题目 Oleg s favorite subjects are History and Math and his favorite branch of mathematic
  • Codeforces Round #677 (Div. 3) 题解

    Codeforces Round 677 Div 3 题解 A Boring Apartments 题目 题解 简单签到题 xff0c 直接数 xff0c 小于这个数的 43 10 43 10 43 1 0 代码 span class to
  • Leetcode 327. 区间和的个数 (前缀和 + 离散化 + 树状数组)

    Leetcode 327 区间和的个数 前缀和 43 离散化 43 树状数组 题目 题意 有多少个连续的子数组 xff0c 其和在 l o w e r
  • 01 Trie 专题

    01 Trie 专题 异或最大值 The xor largest pair 题意 xff1a 异或最大值的模板 一个数和一个序列中一个数的异或最大值是多少 xff1f 要支持询问 思路 考虑把序列插入 xff0c 构建一个 Trie tex
  • DFS序专题

    牛客专题之DFS序 简介 dfs序 每个节点在dfs深度优先遍历中的进出栈的时间序列 xff0c 也就是tarjan算法中的dfn数组 画个图理解一下 xff1a 这棵树的dfs序 xff1a 1 3 2 4 2 5 6 7 6 5 1 那
  • 牛客编程巅峰赛S2第4场题解

    牛客编程巅峰赛S2第4场 牛牛摆玩偶 题目描述 牛牛有 n 2 n 1 0
  • Leetcode第 217 场周赛(思维量比较大)

    Leetcode第 217 场周赛 比赛链接 xff1a 点这里 做完前两题我就知道今天的竞赛我已经结束了 这场比赛思维量还是比较大的 1673 找出最具竞争力的子序列 题目 给你一个整数数组 nums 和一个正整数 k xff0c 返回长
  • 牛客巅峰赛S2第6场题解

    牛客编程巅峰赛S2第6场 A String 题目 题目描述 给出一个仅包含小写字母的字符串s xff0c 你最多可以操作k次 xff0c 使得任意一个小写字母变为与其相邻的小写字母 xff08 ASCII码差值的绝对值为1 xff09 xf
  • 2021牛客寒假算法基础集训营1 题解

    2021牛客寒假算法基础集训营1 题解 比赛地址 xff1a https ac nowcoder com acm contest 9981 官方题解 xff1a https ac nowcoder com discuss 593200 A
  • 自监督学习(self-supervised learning)(20201124)

    看论文总是会看出来一堆堆奇奇怪怪的名词 从远程监督 有监督 半监督 无监督开始 xff0c 最近又看到了一个自监督 首先先对上面的概念进行简述 xff1a 半监督 xff08 semi supervised learning xff09 x
  • mynteye_sdk SDK ubuntu20 编译问题

    1 pcl问题 xff1a usr include pcl 1 10 pcl point types h 508 1 error plus is not a member of pcl traits 508 POINT CLOUD REGI
  • 异常抛出**异常捕获**with用法

    1 对于异常处理 xff0c javascript支持异常处理 xff0c 支持手动抛出异常 需要抛出的时候 xff0c 总是通过throw语句抛出Error对象 语法如下 xff1a throw new Error errorString
  • Java IO流 使用流技术将一张图片从一个目录复制到另一个目录

    题目 xff1a 使用流技术将一张图片从F images目录下 xff0c 复制到D images目录下 复制图片需要使用字节流 xff0c 使用字符流复制会将图片字节码格式进行编码 xff0c 可能会导致图片数据丢失 span class
  • 卡尔曼滤波KF

    KF 根据贝叶斯估计的原理 xff0c 卡尔曼滤波是利用已知系统模型的确定性特性和统计特性等先验知识与观测量获得最有估计 xff0c 在有初始值的情况下 xff0c 从先验值和最新观测数据中得到的新值的加权平均来更新状态估计 1 卡尔曼滤波
  • 解决VS2019提示未能加载项目文件。缺少根元素的错误

    解决VS2019提示未能加载项目文件 缺少根元素的错误 上次win10自动更新关掉了打开的vs xff0c 导致开机后再打开解决方案 xff0c 某个项目一直无法加载 xff0c 提示未能加载项目文件 缺少根元素的错误 迁移报告上显示这个项
  • 实验二 串口通信及中断实验

    一 xff0e 实验目的 xff08 1 xff09 熟悉 MCU 的异步串行通信 Uart 的工作原理 xff08 2 xff09 掌握 Uart 的通信编程方法 xff08 3 xff09 掌握中断的编程方法 xff08 4 xff09