赞
踩
硬件:基于STM32F407VET6编写
软件:使用两个GPIO口,一个用作串口发送TX,一个用作串口接收RX,采用的是定时器模拟 时序。
要模拟串口,首先肯定是需要了解串口的协议,根据协议来编写程序。
UART的通信方式是由1个起始位,8个数据位,包含一个奇偶校验位,和结束位构成 。在本次的设计中默认为波特率为9600,停止位为1位,8位数据位,无奇偶校验位。
先介绍起始位,从高电平跳变为低电平,表示通信开始。再来简单介绍下波特率,单位时间内传送码元符号的个数,波特率9600,也就是1s内传送9600个bit,一个bit所需要的时间为 1000000us / 9600 = 104.166 us,也就是104us。
- #ifndef _S_UART_H_
- #define _S_UART_H_
-
- #include "sys.h"
- #include "delay.h"
-
-
- //定义通信波特率
- #define BaudRate_9600 104 //1000000us/9600=104.1666 发送1个位所需要的时间
-
-
- //GPIO定义
- #define S_Uart_Tx PCout(3) //模拟串口TX端
- #define S_Uart_Rx PCin(4) //模拟串口RX端
-
-
- typedef enum{
- State_State = 0, //起始状态
- State_transfer, //传输状态
- State_Stop, //停止状态
- }UartState;
-
- #define SUartLength 200 //模拟串口缓冲区长度
- extern u8 SUartCnt; //模拟串口缓冲区位置
- extern u8 SUartBuff[SUartLength]; //模拟串口缓冲区
-
-
- void S_Uart_GPIO_Init(void);
- void S_Uart_Send_Buff(u8 *buff,u8 length);
- u8 S_Uart_Rx_Handler(u8 *buf,u8 *length);
-
- #endif
- //模拟串口GPIO初始化
- void S_Uart_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- EXTI_InitTypeDef EXTI_InitStruct;
- NVIC_InitTypeDef NVIC_InitStruct;
-
- //开时钟
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
-
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; //TX GPIOC3
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //推挽输出
- GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOC, &GPIO_InitStruct);
- S_Uart_Tx = 1;
-
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; //RX GPIOC4
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; //上拉输入
- GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
- GPIO_Init(GPIOC,&GPIO_InitStruct);
- }
- //模拟串口发送一个字节
- void S_Uart_One_Tx(u8 Data)
- {
- u8 i;
-
- S_Uart_Tx=0; //起始位
- delay_us(BaudRate_9600);
-
- for(i=0; i<8; i++)
- {
- if(Data & 0x01) //串口协议 先发LSB
- S_Uart_Tx = 1;
- else
- S_Uart_Tx = 0;
-
- delay_us(BaudRate_9600);
- Data >>= 1;
- }
-
- S_Uart_Tx = 1;
- delay_us(BaudRate_9600);
- }
-
- //模拟串口发送数据
- void S_Uart_Send_Buff(u8 *buff,u8 length)
- {
- for(u8 i=0; i<length; i++)
- {
- S_Uart_One_Tx(buff[i]);
- }
- }
需要开启一个定时器中断,对模拟串口的电平进行监视,废话不多说,直接上代码。
- void Time4_Init(u16 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef Tim4_TimeBaseStruct;
- NVIC_InitTypeDef NVIC_InitStruct;
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
-
- Tim4_TimeBaseStruct.TIM_Period = arr; //重载值
- Tim4_TimeBaseStruct.TIM_Prescaler = psc; //预分频值
- Tim4_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
- Tim4_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseInit(TIM4,&Tim4_TimeBaseStruct);
-
- TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
- TIM_Cmd(TIM4,ENABLE);
-
- NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;
- NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
- NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;
- NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
- NVIC_Init(&NVIC_InitStruct);
- }
-
- void TIM4_IRQHandler(void)
- {
- static u8 value=0;
- static UartState M_State = State_State;
- static u8 bit_cnt;
-
- if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update) != RESET)
- {
- TIM_ClearITPendingBit(TIM4,TIM_FLAG_Update);
-
- if(S_Uart_Rx==0 && M_State == State_State) //起始位 下降沿
- {
- M_State = State_transfer; //接收到起始位,状态为传输中
- bit_cnt=0;
- }
- else if(M_State == State_transfer)
- {
- bit_cnt++;
- if(S_Uart_Rx)
- {
- value |= (1<<(bit_cnt-1));
- }
- else
- {
- value &= ~(1<<(bit_cnt-1));
- }
- if(bit_cnt >= 8)
- M_State = State_Stop;
- }
- else if(S_Uart_Rx && M_State==State_Stop)
- {
- bit_cnt=0;
- if(SUartCnt < SUartLength)
- SUartBuff[SUartCnt++] = value; //存入缓冲区
- else
- SUartCnt = 0;
- M_State = State_State; //状态回到起始状态,坐等下一帧数据
- }
- }
- }
-
- //接收串口数据处理
- u8 S_Uart_Rx_Handler(u8 *buf,u8 *length)
- {
- *length = 0;
- if(SUartCnt > 0) //模拟串口缓冲区不为空
- {
- *length = SUartCnt;
- memcpy(buf,SUartBuff,*length); //
-
- SUartCnt = 0;
- }
- return *length;
- }
3.5 主函数调用
- int main(void)
- {
- u16 i;
- u8 len;
- //u8 buff[5]={0,1,2,3,4};
- u8 buff[200];
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
- delay_init(168); //延时初始化
- LED_Init(); //初始化与LED连接的硬件接口
-
- S_Uart_GPIO_Init(); //模拟串口
- Time4_Init(BaudRate_9600,84-1); //104us
-
- while(1)
- {
-
- if(S_Uart_Rx_Handler(buff,&len))
- {
- S_Uart_Send_Buff(buff,len); //将接收到的数据发送出去
- }
-
-
- if(++i %100 == 0)
- {
- i=0;
- LED0 = !LED0;
- //S_Uart_Send_Buff(buff,5);
- }
- delay_ms(10);
- }
- }
单片机将模拟串口接收到的数据用模拟串口发送出去。
好了,内容到此结束了,制作不易,如果对大家有帮助麻烦点个赞,谢谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。