使用了STM32CubeMX及Keil (HAL库)
材料:stm32开发板、USB转TTL?CH340模块、杜邦线、st-link

实验原理:

模拟了异步半双工通信

波特率可变

起始位:1
数据位:8
停止位:1
(1个数据10位)
无校验位


传输一个字符的时候先发送1位起始位,然后是8位数据位(从低位到高位),最后是一位停止位


用1个普通的GPIO口输出(模拟TXD),模拟了以上发送的高低电平,采用定时器延时(一个位对应的电平的持续时间为1000000/波特率 μs)
用1个普通的GPIO口中断输入(模拟RXD),模拟了接收,下降沿触发中断,采用定时器延时,大概在数据位中央采集1次电平数据

实验设计:
使用了PA1作TXD,PA2作RXD,然后连到CH340模块再连到电脑
TIM2延时

实验过程:


测试使用9600的波特率

一开始只实现了初始时发送“hello”,以及环回测试的2位数据正确收发。。。

推断PA1发送功能应该成功了(然而经过逻辑分析仪检测PA1发送的一个位的延时达到106us左右,正常情况应该是104us),PA2接受功能有bug,一次只能正确接受2位数据,后面收到的都是错误的字符,推测是延时上时间误差的问题,而且会自增像空格一样的字符(经过逻辑分析仪的检测其实是ascii码为255的字符,多次测试发现应该是接受完所有字符后又触发了中断,然而后面都是高电平,所以就收到了这个字符)。。。

错误的结果:



然后根据推测改代码,把接收数据中的延时时间改小,忽略掉ascii码为255的字符(简单粗暴的方法。。。)

正确的结果:



STM32CubeMX中的主要设置:







主要代码(以下只有USER CODE BEGIN里的代码):

/* USER CODE BEGIN Includes */

#include

/* USER CODE END Includes */

/* USER CODE BEGIN PV */

/* Private variables ---------------------------------------------------------*/

uint32_t baudrate=9600;  //设置波特率,比如9600bps

uint8_t message[20]; //收到的字符存放的字符数组

uint8_t length=0; //收到的字符数

uint8_t welcome[]="hello"; //要发送的一个初始信息

uint32_t bit_time;

/* USER CODE END PV */


/* USER CODE BEGIN PFP */

/* Private function prototypes -----------------------------------------------*/

void delay_us(uint32_t counter);

void transmitChar(uint8_t ch);

uint8_t receiveChar(void);

void transmitString(uint8_t a[]);

/* USER CODE END PFP */

  /* USER CODE BEGIN 1 */

bit_time=1000000/baudrate; //一个位的时间,单位us

  /* USER CODE END 1 */

  /* USER CODE BEGIN 2 */

transmitString(welcome); //发送初始信息

  /* USER CODE END 2 */


/* USER CODE BEGIN 4 */

 

//延时counter(us)

void delay_us(uint32_t counter){  

counter++;

HAL_TIM_Base_Start(&htim2);

__HAL_TIM_SET_COUNTER(&htim2,counter);

while(counter>1){

counter=__HAL_TIM_GET_COUNTER(&htim2); 

}

HAL_TIM_Base_Stop(&htim2);

}

 

 

//发送字符

void transmitChar(uint8_t ch){

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,(GPIO_PinState)0);

delay_us(bit_time);

uint8_t i,temp;

for(i=0;i<8;i++){

temp=ch&0x01;

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,(GPIO_PinState)temp);

delay_us(bit_time);

ch>>=1;

}

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,(GPIO_PinState)1);

delay_us(bit_time);

}

 

 

//发送字符串

void transmitString(uint8_t a[]){

uint8_t i,j;

j=strlen(a);

for(i=0;i

transmitChar(a[i]);

}

}

 

 

//接收字符

uint8_t receiveChar(void){

uint8_t bit,i,ch=0;

delay_us(bit_time*1.5);

for(i=0;i<8;i++){

bit=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2);

ch>>=1;

if(bit){

ch=ch|0x80;

}

delay_us(bit_time);

}

delay_us(bit_time*0.2);

return ch;

}

 

 

//GPIO的中断回调函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

  /* Prevent unused argument(s) compilation warning */

  UNUSED(GPIO_Pin);

uint8_t ch;

ch=receiveChar();

if(ch=='#'){

uint8_t i;

for(i=0;i

transmitChar(message[i]);

}

length=0;

}

else if(ch!=255){

message[length++]=ch;}

}

 

/* USER CODE END 4 */



实验成果:


实现了19个字符以内的正确收发(20个元素的字符数组,更多字符的接收没有测试。。。)


关键字:STM32F103RCT6  普通IO口  模拟串口 引用地址:用STM32F103RCT6的普通IO口模拟串口的实验

上一篇:STM32JTAG调试接口PB3、PB4复用问题
下一篇:STM32 I/O 作为外部中断输入

推荐阅读

1、跑马灯 IO口的设置 推挽输出 GPIO_Mode_Out_PP 输出高、低电平,连接数字器件(管脚负载能力强、开关速度快) led.c怎么写?#include"led.h"void LED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); ...
一、关于STM32F4在通过串口通信的时候乱码问题 1.刚开始弄得时候,以为和stm32一样配置完串口之后就可以用了,结果后面发现串口打印出来的东西全是乱码。后面发现是STM32F4的固件库中使用的频率是25Mhz,而板子上的外部晶振是8Mhz的。因此需要去固件库的stm32f4xx.h中把HSE_VALUE改成8Mhz就可以了。2.还有一种问题是,如果使用的是电平转换的问题。要直接...
工业机器人和机床应用的时序挑战分析 工业机器人和机床应用涉及加工空间中多个轴的精确、协调运动。机器人通常具有六个需要统筹控制的轴,如果机器人可沿轨道移动,则将会有七个轴。尽管有应用会使用到多达12个轴,其中刀具和工件均在空间进行相对移动,但在数控加工中,5轴加工属于较为常见的应用。每个轴由一个伺服驱动器和一个组成,有时还包括一个...
前面程序运行,发现从Nand Flash启动和从Nor Flash启动表现是不一样的。设置成Nand Flash启动没有问题 显示ABCDE…设置成NOor Flash启动则显示AAA…这是什么原因呢?Nor启动Nor Flash就被认为是0地址,g_Char被放在0x700后面。CPU上电后从0地址开始执行,它能读取Nor Flash上的代码,打印出A,当进行g_Char++的时候,写操作操作无效,下次读取的数...

史海拾趣

问答坊 | AI 解惑

求教ICCAVR编译中出现的问题

各位大哥,小弟刚学单片机遇到一个问题,希望大家不吝赐教,先行谢过了。 单片机用的是ATMEGA8L,编译用的是ICCAVR,可是一编译就显示出错 F:\\AVR\\ICCAVR\\icc\\bin\\imakew -f test1.mak iccavr -c -IF:\\AVR\\ICCAVR\\icc\\include\\ ...…

查看全部问答∨

基于max038的函数发生器的问题

用max038产生的高频信号有很大的干扰如何滤除??产生的波形很粗!!!仔细看像扭得麻花?????这如何解决???为什么4051不能换挡??这也是个麻烦事!!希望哪个专家高手给点意见和经验!!!谢谢!!…

查看全部问答∨

电脑公司诊断卡代码

电脑公司诊断卡代码…

查看全部问答∨

关于KEIL

如何在KEIL下使用其集成的逻辑分析仪?能给个详细的说明吗?  …

查看全部问答∨

如何将IE默认的播放器换成自己所写的播放器

由于IE默认的WMP播放视频,音频时卡,所以打算加入自己写的视频播放插件?…

查看全部问答∨

如何实现类似资源管理器的界面程序

用EVC实现这个功能,界面方面用WTL,希望有大虾指点下 现在很是困惑,不知道如何着手...…

查看全部问答∨

C6713实时语音处理程序问题请教,附代码

#include <std.h> #include <swi.h> #include <csl_edma.h> #include <csl_irq.h> #include <csl_mcbsp.h> #include \\"aic23.h\\" #include <csl_cache.h> #include \\"switestcfg.h\\" Uint32 i; Ui ...…

查看全部问答∨

我想不重烧NK,修改wince6开机画面,mini2440平台,求教

我查看了下,startlogo.c里面的logo数组便宜到了nk.exe中,但是我在wince6中把windows下面的nk。exe替换了,开机画面仍然不变,求教如何实现不重烧nk实现换wince开机画面的方法(非nboot画面)…

查看全部问答∨

请教关于STM32 CAN与USART同时通讯的问题

小弟在用MCU为 STM32F103ZET6 的一块板子学习当中,现在USART和CAN已经分别调通。 现在想请教一下各位高手: 我手边有一台可以通过232串口与PC通讯的机器,是通过PC上一个软件发送指令来控制通讯,但是限于232传输距离不够,我想先用我自己板子上 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved