中科因仑“3+1”工程特种兵精英论坛
标题:
STM32实现485通信(测试简易485转232模块)
[打印本页]
作者:
惨淡的人生
时间:
2016-6-20 19:29
标题:
STM32实现485通信(测试简易485转232模块)
STM32学习笔记4 竹天笑
此学习笔记的主要目的是测试一下我刚焊接的简易485转232模块,由于是初学者,当初在买开发板的时候没有想到考虑到485实验。485实验需要一对开发板来测试,或者一个485转232模块接电脑用串口调试助手测试。485实验一直搁置而没有做,面临工作需要,一直想做一下。而今天在逛论坛的时候,看到下图眼睛都冒光了,精神顿时来了,一吃完晚饭就迫不及待的测试起来。(先声明,本人刚开始工作,从未接触485通信,因此本文仅供参考,肯定出现很多错误,请大神指正。)
简易的485转232模块
此图来自阿莫电子论坛的帖子《超级简单的RS485转RS232电路》
本人焊接的实物图如下:
左边是我买的USB转232,右边为我焊接的232转485
硬件搭建完毕,当然要用程序测试才行,使用的开发板是红牛三代,有关485接口的电路图如下:
接下来上程序(程序简单流程:1、串口调试助手发数据->usb转232模块->232转485模块->开发板485接口,2、然后将接收的数据发送出来->232转485模块-> usb转232模块->串口调试助手显示。)
初始化:很晚了,明天还要上班就不注解了(类似注解请看本人上一篇帖子: STM32实现USART+DMA接收未知长度的数据和发送
http://www.amobbs.com/thread-5486343-1-1.html
)
void USART_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO , ENABLE);
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3 , ENABLE);
/*
* USART3_TX -> PB10 , USART3_RX -> PB11 , 485_DIR -> PB2
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
// USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
//USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
USART_ITConfig(USART3, USART_IT_IDLE , ENABLE);//开启空闲,帧错,噪声,校验错中断
USART_Cmd(USART3, ENABLE);
USART_ClearFlag(USART3,USART_FLAG_TC);
DMA_InitTypeDef DMA_InitStructure;
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA1
/* DMA1 Channel3 (triggered by USART3 Rx event) Config */
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004804;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART_RECEIVE_DATA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 512;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE);
/* Enable USART2 DMA RX request */
USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//Enable DMA Channel4 Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
主程序:好像什么都没有,呵呵,数据接收与发送都在中断中实现。数据接收使用DMA接收,并使用USART空闲总线中断处理接收的数据。
int main(void)
{
USART_Configuration();
printf("485to232测试\r\n");
/* Infinite loop */
while (1){
}
}
中断服务函数:下面我加红部分是232通信与485通信不一致的地方。485通信的速度是无法与232相比的。
void USART3_IRQHandler(void)
{
u16 DATA_LEN;
u16 i;
if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
{
DMA_Cmd(DMA1_Channel3, DISABLE);//关闭DMA,防止处理其间有数据
DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel3);
//由于485是半双工的,所以要么只能接,要么只能发。
DIR485_Send();//485发送打开
for(i=0;i<DATA_LEN;i++)
{
USART_SendData(USART3, USART_RECEIVE_DATA
);
Delay(10000);//此句非常重要,不知道是我这个简易模块的问题,还是485通信速度的问题,删除就出错。
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}
DIR485_Receive();//485发送完,就必须打开 485接收
DMA_ClearFlag(DMA1_FLAG_GL3 | DMA1_FLAG_TC3 | DMA1_FLAG_TE3 | DMA1_FLAG_HT3);//清标志
DMA1_Channel3->CNDTR = 512;//重装填
DMA_Cmd(DMA1_Channel3, ENABLE);//处理完,重开DMA
//读SR后读DR清除Idle
i = USART3->SR;
i = USART3->DR;
}
if(USART_GetITStatus(USART3, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET)//出错
{
USART_ClearITPendingBit(USART3, USART_IT_PE | USART_IT_FE | USART_IT_NE);
}
USART_ClearITPendingBit(USART3, USART_IT_IDLE);
}
void DMA1_Channel3_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA1_IT_TC3);
DMA_ClearITPendingBit(DMA1_IT_TE3);
DMA_Cmd(DMA1_Channel3, DISABLE);//关闭DMA,防止处理其间有数据
DMA1_Channel3->CNDTR = 512;//重装填
DMA_Cmd(DMA1_Channel3, ENABLE);//处理完,重开DMA
}
结束,呵呵,测试结果,简易模块非常不错,肯定不能用于产品,但是做测试完全是可行的。唯一不足的就是速度上不行。今天只试了9600波特率,明天继续测试,今天PIC开发板测试没通过,打算用我的PIC开发板测试。
程序包下载地址:
http://115.com/file/e7csjmze#
USART_485(测试485转232模块).rar
说明文档下载地址:
http://115.com/file/anpjl2av#
STM32实现485通信(测试简易485转232模块).doc
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/)
Powered by Discuz! X3.4