论坛元老
- 积分
- 3308
- 金钱
- 3308
- 注册时间
- 2013-4-10
- 在线时间
- 328 小时
|
发表于 2016-4-12 19:58:30
|
显示全部楼层
本帖最后由 likunxue 于 2016-4-12 20:02 编辑
串口2的程序好像跟有没有用UCOS是一样的啊, 有UCOS的最多在中断函数里加上 中断调度指令就行了吧!
我倒是有一个485通信的,你自已看看,我用在设备上2年了,没有出现过问题
/**************************************************************************************
模块名称: RS485驱动代码(第七代自动机)
文件名称: RS485.C
版 本: V1.0
说 明:
日 期: 2013年5月17日
作 者: likunxue
C P U : STM32F103ZE 主频: 72MHz
Copyright (C), 2013-2020, 贵州惠水昶达数控有限公司
修改记录: 2013年9月2号修改为新主板 支持UCOS操作系统
**************************************************************************************/
#include "sys.h"
#include "rs485.h"
#include "delay.h"
#include "MOTOR.H" //步进电机配置头文件
#include "CanShuSheZhi.H" //机台参设置函数部份
#include "malloc.h" //内存管理
#if SYSTEM_SUPPORT_UCOS //如果使用ucos,则包括下面的头文件即可
#include "includes.h" //ucos 使用
#include "APP_CFG.H" //工程项目文件
#endif
vu32 RX_Lang; //串口接收的32位参数
vu16 RX_BYTE; //串口收到的16位参数
vu8 RX_DAT; //串口接收中的低7位数据寄存器
vu8 RX_QianZhiLing; //串口接收中的低位接收标志位
vu8 RX_STR; //串口接收缓存区指针
vu8 RX_OK; //串口接收完成标志寄存器
vu8 RX_Buf[SUA_SIZE]; //串口接收缓存数据区
vu8 TX_Buf[SUA_SIZE]; //串口2发送缓存区
/***************************************************************************************
函 数 名: DMA1的各通道配置
这里的传输形式是固定的,这点要根据不同的情况来修改
从存储器->外设模式/8位数据宽度/存储器增量模式
调 用: UART_DMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar)
参 数: DMA_CHxMA通道CHx
cpar:外设地址
cmar:存储器地址
返 回 值: 无
***************************************************************************************/
void UART_DMA_Config(u32 cpar,u32 cmar)
{
RCC->AHBENR |= 1<<0; //开启DMA1时钟
delay_us(5);
DMA1_Channel7->CPAR = cpar; //DMA1 外设地址
DMA1_Channel7->CMAR = cmar; //DMA1,存储器地址
DMA1_Channel7->CCR = 0x00000000; //复位
BIT_ADM(DMA1_Channel7->CCR, 4) = 1; //从存储器读
BIT_ADM(DMA1_Channel7->CCR, 5) = 0; //普通模式
BIT_ADM(DMA1_Channel7->CCR, 6) = 0; //外设地址非增量模式
BIT_ADM(DMA1_Channel7->CCR, 7) = 1; //存储器增量模式
BIT_ADM(DMA1_Channel7->CCR, 8) = 0; //外设数据宽度为8位
BIT_ADM(DMA1_Channel7->CCR,10) = 0; //存储器数据宽度8位
BIT_ADM(DMA1_Channel7->CCR,12) = 1; //中等优先级
BIT_ADM(DMA1_Channel7->CCR,14) = 0; //非存储器到存储器模式
}
/*************************************************************************************
函 数 名: 初始化IO 串口2
调 用: 无
参 数: pclk1CLK1时钟频率(Mhz)
bound:波特率
反 回 值: 无
**************************************************************************************/
void RS485_Init(u32 pclk1,u32 bound)
{
float temp;
u16 i,mantissa,fraction;
for(i =0; i< SUA_SIZE; i++){RX_Buf = 0; TX_Buf = 0;}//接收缓存区
RX_BYTE = 0; //串口收到的16位参数
RX_DAT = 0; //串口接收中的低7位数据寄存器
RX_QianZhiLing = 0; //串口接收中的低位接收标志位
RX_STR = 0; //串口接收缓存区指针
RX_OK = 0; //串口接收完成标志寄存器
temp=(float)(pclk1*1000000)/(bound*16);//得到USARTDIV
mantissa=temp; //得到整数部分
fraction=(temp-mantissa)*16; //得到小数部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR |= 1<<2; //使能PORTA口时钟
GPIOA->CRL &= 0xFFFF00FF; //IO状态设置
GPIOA->CRL |= 0x00008B00; //IO状态设置
GPIOA->ODR |= 1<<3; //置上拉
RCC->APB2ENR |= 1<<4; //使能外设PORTC时钟
GPIOC->CRL &= 0xffffff00; //PC0,PC1设为输出
GPIOC->CRL |= 0x00000033;
GPIOC->ODR |= 1<<0; //置上拉,初始化高电平
GPIOC->ODR |= 1<<1; //置上拉,初始化高电平
RCC->APB1ENR |= 1<<17; //使能串口时钟
RCC->APB1RSTR |= 1<<17; //复位串口2
RCC->APB1RSTR &= ~(1<<17); //停止复位
//波特率设置
USART2->BRR=mantissa; //波特率设置
USART2->CR1 |= 1<<13; //串口2使能(UE,USATR)
USART2->CR1 |= 1<<2; //接收使能(RE)
USART2->CR1 |= 1<<3; //发送使能(TE)
USART2->CR1 |= 1<<8; //PE中断使能
USART2->CR1 |= 1<<5; //接收缓冲区非空中断使能
USART2->CR3 = 1<<7; //使能串口2的DMA发送
//DMA1通道7,外设为串口2,存储器为USART2_TX_BUF
UART_DMA_Config((u32)&USART2->DR,(u32)TX_Buf); //初始化DMA
MY_NVIC_Init(0,0,USART2_IRQn,4); //抢占5,子优先级0,组4
}
/*************************************************************************************
函 数 名: RS485中断接收函数(双字节指令模式)
调 用: 无
参 数: 无
反 回 值: 无
自定义数据接收格式
**************************************************************************************/
void USART2_IRQHandler(void)
{
#if SYSTEM_SUPPORT_UCOS //如果使用ucos,
OSIntEnter(); //进入中断
#endif
if(USART2->SR&(1<<5)) //接收到数据
{
u8 K = USART2->DR; //读取串口数据
USART2->SR &= ~(1<<5); //清中断接收标志位
if(K < 0x80){RX_DAT = K;RX_QianZhiLing = 0xE5;}//数据低7位
else{
u8 Bul = K & 0xf8; //得到指令码
if(RX_QianZhiLing == 0XE5)
{ //双字节指令解码部份
switch(Bul)
{
case 0x80:{//是数据字节(0x80)
if(RX_STR >SUA_SIZE)RX_STR = 0;
RX_Buf[RX_STR ++ ]= (K <<7)+RX_DAT;//RX_BYTE;
}break;
case 0x88:{RX_STR = 0; RX_Buf[RX_STR ++] = (K <<7)+RX_DAT;}break;//多字节参数初始化
case 0x90:{//接收双字节数据包,10位有效数据
RX_BYTE = (((u16)(K & 0x07))<<7)|RX_DAT; //得到有效数据(10位)
RX_OK = 0xE5; //置接收完成标志
}break;
case 0x98:{//收到电机坐标值或编码器的状态值(双字节,16位)
RX_BYTE = (((((u16)(K & 0x07))<<7)|RX_DAT)<<8)+ RX_Buf[0]; //得到参数
RX_OK = 0xE5;//置接收完成标志
}break;
case 0xA0:{//接收4个字节 32位
RX_Lang = (K <<7)+RX_DAT;
RX_Lang <<= 8;
RX_Lang |= RX_Buf[2];
RX_Lang <<= 8;
RX_Lang |= RX_Buf[1];
RX_Lang <<= 8;
RX_Lang |= RX_Buf[0];
RX_OK = 0xE5;//置接收完成标志
}break;
}
}
RX_QianZhiLing = 0x80; //清标志位
}
}
#if SYSTEM_SUPPORT_UCOS //如果使用ucos,
OSIntExit(); //触发任务切换软中断
#endif
}
/**************************************************************************************
函 数 名: 申请485总线使用权等待函数
调 用: SUA_ShiYongQuan(u32 JiShuQi)
参 数: JiShuQi 等待计数器
返 回 值: 无
说 明: 如果总线在使用中,则按给定的时间等待总线工作完成 然后再置使用标志位
如果定时器2在工作中,禁止申请
***************************************************************************************/
void SUA_ShiYongQuan(void)
{
u8 err;
while(TIM_TR2 == 1); //电机工作期间,禁止申请485总线
OSMutexPend(sem_SUA,100,&err); //申请互斥信号量,会在址一直等待
if(err == OS_ERR_NONE )
{
while(DMA1_Channel7->CNDTR != 0); //等待通道7传输完成
BIT_ADM(DMA1_Channel7->CCR ,0) = 0; //关闭DMA传输
return;
}
else{
OSMutexPost(sem_SUA); //释放485使用权
ERR_BPPK("485总线占用超时了 ");
}
} |
|