你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32L4零基础学习笔记(五)串口通讯之简单接收

[复制链接]
D5Power 发布时间:2017-11-6 08:36
本帖最后由 D5Power 于 2017-11-16 16:44 编辑

向前翻页:STM32L4零基础学习笔记(四)串口通讯

前面的笔记中,小D研究了如何通过串口模块(CH340)进行数据的发送。在本篇笔记中,我们会尝试从电脑发送数据到开发板。并通知电脑已经收到数据。

一、发送数据的扩展——实现printf

printf是一个小D非常喜欢的调试工具。而在前面的代码编写中,我发现这玩意写进去好像没有什么卵用。于是查了一下资料。原来在单片机中,printf是要自己通过串口发送来实现的(实际上输出的内容会出现在sscom软件中。)至于原理是怎么样的,现在不去深究。直接把代码贴进自己项目先用着。在此感谢各位前辈的无私奉献。

首先,需要进行一个函数声明(可以直接写在main.c中)

int fputc(int ch,FILE *f);

然后,进行函数实现:

int fputc(int ch,FILE *f)
{
uint8_t temp[1]={ch};
HAL_UART_Transmit(&huart2,temp,1,2);
}

从代码中不难看出,其实就是通过HAL库的发送方法,将信息通过UART2发送出去。如果你的项目里使用的是其他串口,请注意修改。

现在,只需要正常的使用printf,在SSCOM软件中就可以看到输出了。可以开心的用printf调试啦。

二、一个小技巧

仔细观察STMCube帮我们生成的代码,小D发现,注释中标明了用户自己编写代码的区域。例如:

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

或者

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

因为我们经常需要在后期通过STMCubeMX修改项目配置,进而重新生成代码。此时,写在这些注释中间的代码,是不会被替换掉的。所以,养成好的习惯很重要。记得把自己的代码写在这些注释块中间,可以省掉不少重复敲代码的时间呢。

三、进入正题

在翻阅网上的资料后,小D决定使用来HAL_UART_Recive_IT来进行接收。于是冒冒失失就按照例子把代码敲进去了。结果调试发现,并没有什么卵用。传说中的HAL_UART_RxCpltCallback方法根本不会运行。那么,到底是为什么呢?

HAL_UART_Recive_IT并不会影响主程序的运行,而是在收到规定长度的数据后,再通过HAL_UART_RxCpltCallback进行回调。那么,应该是中断没有被触发。经过多方查证,终于发现。中断模式必须要自己在STMCubeMX中配置,才会被启用。很多的新手引导贴都忽略了这个环节(估计是因为太基础了吧)。

打开STMCubeMX,通过Open Project打开自己的项目(啥?你不知道怎么打开,可以直接找到项目的保存目录,里面有一个.ioc的文件,双击,或打开项目时选择它都可以)。

然后到配置界面(Configration)中,点击对应的串口,例如我的是USART2,然后找到中断设置(NVIC Setting),设置为允许中断(打勾即可)。如下图:

1.png

设置好后,重新生成代码。如果忘记了如何重新生成代码,可以参考本篇笔记

首先,我们需要一个用来接收数据的缓冲区。因此,在全局变量中,我们声明了buffer,用来接收数据:

uint8_t buffer[512] = "";

然后,回到MDK中,打开main.c。在main函数中的while循环前,加入以下代码:

if(HAL_UART_Receive_IT(&huart2,(uint8_t *)&buffer,1)!=HAL_OK)
  {
    printf("Recived error.");
  }

然后,实现HAL_UART_RxCpltCallback方法:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    printf("Recived data.");
    HAL_UART_Receive_IT(&huart2,(uint8_t *)&buffer,1);
}

当收到数据的时候,打印Recived data。

编译并上传入开发板,然后运行。每次在SSCOM中点击发送数据。就会收到开发板返回来的打印信息了。如下图:

2.png

说明开发板已经收到我们的数据了。并且还给出了响应。不过每次只收1个字节这种事情的确比较蛋疼。在实际的通讯中肯定不方便。原来在开发游戏的时候,我们一般都会采用自己的二进制协议来传输数据。那么,能不能把这些协议在单片机上实现呢?动手研究一下吧。

下一篇:STM32L4零基础学习笔记(六)串口通讯之踩到的坑

----------------我是淫荡的分割线----------------

  广告时间,编写中的笔记会在我个人的公众号进行,请各位高手斧正。

qrcode_for_gh_bb8c73d98b29_344.jpg

评分

参与人数 1 ST金币 +6 收起 理由
MrJiu + 6 支持基础知识。。。

查看全部评分

收藏 评论7 发布时间:2017-11-6 08:36

举报

7个回答
D5Power 回答时间:2017-11-6 08:43:49
汗,是刚好赶上管理员上班么,秒审啊@creep
Inc_brza 回答时间:2017-11-6 09:02:30
重定向已经太low了,
可以直接调用vsnprintf,这样用户只需要实现一个串口发送str的函数即可,有时候log不仅仅是串口,还可以是lcd、sd卡等等,所以这个发送str的目的地可以随意设置,比重定向fputs、fgets方便多了!
D5Power 回答时间:2017-11-6 09:07:38
Inc_brza 发表于 2017-11-6 09:02
重定向已经太low了,
可以直接调用vsnprintf,这样用户只需要实现一个串口发送str的函数即可,有时候log不 ...

收到!感谢指教
MrJiu 回答时间:2017-11-7 11:31:08
顶。。。
D5Power 回答时间:2017-11-7 15:28:00
本帖最后由 D5Power 于 2017-11-7 15:29 编辑

感谢版主大大打赏
顺便请教下,为什么开发板收到由SSCOM发过来的数据,跟我发出的不一样。哪怕只有1个字节
april1818 回答时间:2017-11-17 00:14:30
请问 if(HAL_UART_Receive_IT(&huart2,(uint8_t *)&buffer,1)!=HAL_OK)
  {
    printf("Recived error.");
  }
为什么要写在while(1)前呢
还有 如果不调用回调函数 可以吗
D5Power 回答时间:2017-11-17 08:31:39
april1818 发表于 2017-11-17 00:14
请问 if(HAL_UART_Receive_IT(&huart2,(uint8_t *)&buffer,1)!=HAL_OK)
  {
    printf("Recived error."); ...

Recive_IT是会触发中断的。这样写是因为我希望在中断中去处理收到的数据(比如推进自己的缓冲区,等待解包处理。)。因此,在主循环开始前,设置收取1个字节的中断。然后在中断函数中,处理完这个字节,继续设置下一个中断。从而使中断连续运行。

具体后续的写法,可以参考第七篇笔记:简单数据协议

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版