完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
IO口配置 串口通信需要发送(TX)和接收(RX)两根通信线(半双工模式)。因此,我们需要将两个IO端口分别配置成TX和RX。 1.IO_TX发送配置:IO基本模式配置(具体请看前几期IO口配置博客),开启外部中断,触发模式设置为下降沿触发; 代码如下: #define VM_UART_TXD_PORT_OUT PC_DDR|=1<<5 ;PC_CR1|=(1<<5 );PC_CR2 &=~(1<<5)//设定为输出 #define VM_UART_TXD_PORT_IN PC_DDR&=~(1<<5 );PC_CR1|=(1<<5 );PC_CR2&=~(1<<5 )//设定为输入 2.IO_RX发送配置:IO基本模式配置(具体请看前几期IO口配置博客),开启外部中断,触发模式设置为上升沿和下降沿触发 代码如下: #define VM_UART_RXD_PORT_IN PB_DDR&=~(1<<4);PB_CR1|=(1<<4);PB_CR2&=~(1<<4) //设置只上拉输入 不中断 #define VM_UART_RXD_PORT_INT_IN PB_DDR&=~(1<<4);PB_CR1|=(1<<4);PB_CR2|=(1<<4) //设置只上拉输入 中断 3.初始化IO口,并配置中断及编写中断服务函数 代码如下: /************************************************************************** 全局变量 **************************************************************************/ u8 vm_UART_RX_P;//接收缓存指针 u8 vm_UART_RX_BUF[vm_UART_RX_BUF_L];//接收缓存 u8 vm_UART_RX_byte;//扩展串口 字节缓冲区 u8 vm_UART_RX_bit;//扩展串口 计算位数 u8 vm_UART_TX_byte;//扩展串口 字节缓冲区 u8 vm_UART_TX_bit;//扩展串口 计算位数 u8 vm_uart_tx_flag;//正在发送标志 u8 vm_uart_rx_flag;//正在接收标志 /**************************************************************************/ void IO_EXTI_init(void) { VM_UART_TXD_PORT_IN;//发送初始化 //外部中断 EXTI_CR1 &=~(3<<4);//清零 EXTI_CR1 |=2<<4;//下降沿触发 VM_UART_RXD_PORT_INT_IN;//接收初始化 //外部中断 EXTI_CR1 &=~(3<<2);//清零 EXTI_CR1 |=3<<2;//上升沿和下降沿触发 } //中断服务函数 #pragma vector=7 __interrupt void EXTI_PORTC_IRQHandler(void) { //外中断一次收一个字节,只识别起始位 if((PB_IDR &0x10) == 0) { TIM1_START;//启动定时器 vm_UART_RX_byte = 0; vm_UART_RX_bit = 0; VM_UART_RXD_PORT_IN; //只上拉输入 不中断 vm_uart_rx_flag = 1;//开启发送 } } 波特率配置 由实验原理我们可以知道波特率可以通过配置定时器来设置,具体计算公式如下所示: stm8波特率计算:主时钟频率/分频系数/波特率=装载值 例:波特率9600 主时钟频率16MHz 分频系数1 初值=16x10^6/9600=1667 根据公式,我们可以求得初值,然后配置定时器自动装载值,分频系数,计数器模式,开启中断!开启中断!开启中断!重要事情说三遍! 发送 定时器配置(此处初始化TIM2定时器实现发送功能),中断服务函数及串口发送函数 代码部分: //1.定时器2初始化 void TIM2_Configuration(u16 time, u8 en) { TIM2_CR1|=1<<7;允许自动装载值 TIM2_PSCR = 0;//预分频系数 TIM2_ARRH = (uint8_t)(time >> 8); TIM2_ARRL = (uint8_t)(time & 0xff); //自动装载值 TIM2_IER = 1;//中断使能 if(en != 0) { TIM2_CR1 |= 1<<0;//使能计数器 } } //2.定时器2中断服务函数 #pragma vector=0xF __interrupt void TIM2_UPD_OVF_BRK_IRQHandler(void) { TIM2_SR1&=~(1<<0);//清空标志位 if(vm_UART_TX_bit < 8)//判断数据位数 { if((vm_UART_TX_byte & 0x1) == 0x1) { VM_UART_TXD_PORT_WriteHigh; } else { VM_UART_TXD_PORT_WriteLow; } vm_UART_TX_byte /= 2; } else { VM_UART_TXD_PORT_WriteHigh; if(vm_UART_TX_bit > 8)//判断数据位数 { vm_uart_tx_flag = 0; //设置为发送完毕 VM_UART_TXD_PORT_IN; TIM2_STOP;// } } vm_UART_TX_bit++; } //3.模拟串口发送函数,此处编写了三个发送函数,根据自己需求调用 void vm_UARTsend_byte(u8 byte) { while(vm_uart_tx_flag == 1); //检查是否发送完毕 vm_uart_tx_flag = 1; VM_UART_TXD_PORT_OUT; VM_UART_TXD_PORT_WriteLow; vm_UART_TX_bit = 0; vm_UART_TX_byte = byte; TIM2_START; //计数器置零,启动定时器 } void vm_UART_SendString(u8 *Data, u16 len) { u16 i; for(i=0; i < len; i++) vm_UARTsend_byte(Data); } void vm_UART_SendStr(u8 *str) { u16 i = 0; while((*(str+i)) != 0) { vm_UARTsend_byte(*(str+i)); i++; } } 接收 配置定时器1(TIM1),中断服务函数(包含接收部分) 代码如下: //定时器1初始化 //通过设计算定时器初值来设置波特率 /*stm8波特率计算:主时钟频率/分频系数/波特率=装载值*/ void TIM1_Configuration(u16 time, u8 en) { TIM1_CR1 |= 1<<7;//允许自动装载值 /*设置自动装载值*/ TIM1_ARRH = (uint8_t)(time >> 8);//取高八位 TIM1_ARRL = (uint8_t)(time)&0x00ff;//取低八位,高八位清零 /* 设置分频系数*/ TIM1_PSCRH = (uint8_t)(0x0000 >> 8); TIM1_PSCRL = (uint8_t)(0x0000)&0x00ff; /* 选择计数器模式 */ TIM1_CR1&= ~(1<<4);//向上计数 TIM1_CR1&=~(1<<3);//循环计数 TIM1_CR1&=~(1<<2);//更新请求源 TIM1_CR1 = 0;//清零 /* 设置重复计数模式 */ TIM1_RCR = 0x00; /* 设置允许中断 */ TIM1_IER = 1;//中断使能 if(en != 0) { TIM1_CR1 |= 1<<0;//使能计数器 } } //2.定时器1中断服务函数 #pragma vector=0xD __interrupt void TIM1_UPD_OVF_TRG_BRK_IRQHandler(void) { TIM1_SR1&=~(1<<0);//清空标志位 if((PB_IDR &0x10) == 0) { vm_UART_RX_byte /= 2; } else { vm_UART_RX_byte /= 2; vm_UART_RX_byte |= 0X80; } vm_UART_RX_bit++; if(vm_UART_RX_bit >= 8) { (uint8_t)PC_ODR_ODR4>0?0:1;//高取反,低取高,必须配置为输出 TIM1_STOP;//停止定时器 VM_UART_RXD_PORT_INT_IN; vm_uart_rx_flag = 0; vm_UART_RX_bit = 0;// vm_UART_RX_BUF[vm_UART_RX_P] = vm_UART_RX_byte; //一个字节时接收完毕 vm_UART_RX_P++; if(vm_UART_RX_P >= vm_UART_RX_BUF_L)vm_UART_RX_P = 0; //接收指针 } } 主函数部分 1.时钟及所有外设初始化 2.开启全局中断 3自行添加代码部分 总结 本教程详细讲解了STM8单片机IO口模拟串口通线,实习那真正串口,大大降低了成本。以下是串口发送的效果图。 写得不好,多多指教。 |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1102浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2301浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1857浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 01:10 , Processed in 1.200589 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号