OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8146|回复: 5

战旗开发板上CoOS 操作系统实例(三)之多串口收发(超时法)

[复制链接]

7

主题

10

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
230
金钱
230
注册时间
2012-9-20
在线时间
4 小时
发表于 2013-9-14 00:28:49 | 显示全部楼层 |阅读模式
 

CooCox CoOS 是一款针对ARM Cortex-M系列芯片而设计的实时系统内核。

CoOS特征:

  • 免费并开源
  • ARM Cortex M3及M0定制操作系统
  • 高度可裁剪性,最小系统内核仅974Byte
  • 支持优先级抢占和时间片轮转
  • 自适应任务调度算法
  • 中断延时时间趋近于零
  • 堆栈溢出检测
  • 信号量、邮箱、队列、事件标志、互斥等同步通信方式
  • 支持多种编译器:ICCARM、ARMCC、GCC

#include <CoOS.h>
#include "stm32f10x.h"
#include "usart.h"

OS_STK taskA_stk[128];  //建立一个任务栈A
OS_TCID sftmr; //定义一个软件定时器变量

void LED_GPIO_Init(void)
{
 
 GPIO_InitTypeDef Weiqi_GPIO_InitStru;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO,ENABLE);
 
 Weiqi_GPIO_InitStru.GPIO_Pin = GPIO_Pin_5;
 Weiqi_GPIO_InitStru.GPIO_Speed = GPIO_Speed_50MHz;
 Weiqi_GPIO_InitStru.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
 GPIO_Init(GPIOB,&Weiqi_GPIO_InitStru);
 
 Weiqi_GPIO_InitStru.GPIO_Pin = GPIO_Pin_5;
 Weiqi_GPIO_InitStru.GPIO_Speed = GPIO_Speed_50MHz;
 Weiqi_GPIO_InitStru.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
 GPIO_Init(GPIOE,&Weiqi_GPIO_InitStru);
 
  GPIO_SetBits(GPIOB,GPIO_Pin_5);
  GPIO_SetBits(GPIOE,GPIO_Pin_5);
 
}

void TaskA(void* pData)
{

 for(;;)
 {
  u8 i;
  if(USART_RX_STA&0x8000)
  {
   printf("\r\nThis is Your Input Data:\r\n");
   for(i=0;i<(USART_RX_STA&0x7FFF);i++)
   {
    printf("%c",USART_RX_BUF);
   }
   USART_RX_STA=0;
  }

 }
}

int main(void)
{
  SystemInit(); //初始化系统设置时钟为72Mhz
  
  LED_GPIO_Init();
  
  uart_init(9600);
  
  CoInitOS ();  //操作系统初始化

  /*
  
     [IN1]创建任务的函数体
     [IN2]任务函数体的传入参数列表
     [IN3]任务优先级
     [IN4]任务栈起始地址
     [IN5]任务堆大小
  
  */
  sftmr = CoCreateTmr(TMR_TYPE_PERIODIC,1,1,SftTmrCallBack); //创建一个软件定时器 用于串口超时计时
  CoStartTmr(sftmr); //启动软件定时器
  CoCreateTask (TaskA,0,0,&taskA_stk[128-1],128); //创建任务A

  CoStartOS ();  //启动操作系统开始多线程
  
  while (1);  //代码永远执行不到这里
}




串口部分代码


#include "sys.h"
#include "usart.h" 

//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB  
#if 1
#pragma import(__use_no_semihosting)            
//标准库需要的支持函数                
struct __FILE
{
 int handle;

};

FILE __stdout;      
//定义_sys_exit()以避免使用半主机模式   
_sys_exit(int x)
{
 x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{     
 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    USART_SendData(USART1,(uint8_t)ch);  
 return ch;
}
#endif

/*使用microLib的方法*/
 /*
int fputc(int ch, FILE *f)
{
 USART_SendData(USART1, (uint8_t) ch);

 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} 
  
    return ch;
}
int GetKey (void)  {

    while (!(USART1->SR & USART_FLAG_RXNE));

    return ((int)(USART1->DR & 0x1FF));
}
*/
 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误    
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.

u16 USART_RX_STA=0;       //接收状态标记
u8 RxTimeOut=0;

//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound){
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
 USART_InitTypeDef USART_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
  USART_DeInit(USART1);  //复位串口1
  //USART1_TX   PA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
  
    //USART1_RX   PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PA10


   //USART 初始化设置

 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
 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(USART1, &USART_InitStructure); //初始化串口
#if EN_USART1_RX    //如果使能了接收 
   //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //子优先级3
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能
 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
  
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
#endif
    USART_Cmd(USART1, ENABLE);                    //使能串口

}

void USART1_IRQHandler(void)                 //串口1中断服务程序
{
 u8 Res;
 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  {
    RxTimeOut=3;//字符串超时等待时间;30毫秒;
    Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
     USART_RX_BUF[USART_RX_STA]=Res;
    USART_RX_STA++;
    if(USART_RX_STA>63)  //解决之前遇到的溢出覆盖问题
    {
     USART_RX_STA=0;
    }

    }
}

void SftTmrCallBack(void)
{
  //软件定时器内不能使用延时函数 不然会导致内核异常
  if(RxTimeOut>0)
  {
   RxTimeOut--;
  }
  else
  {
   if(USART_RX_STA>0)
   {
    USART_RX_STA|=0x8000;
   }
  }
 
}
#endif

 

实验现象:

发送什么字符串就会原样的显示回来

Coos-串口实验.zip

366.74 KB, 下载次数: 892

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

51

主题

1455

帖子

3

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2613
金钱
2613
注册时间
2011-1-25
在线时间
176 小时
发表于 2013-9-14 08:01:10 | 显示全部楼层
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-9-14 11:12:17 | 显示全部楼层
谢谢分享,cool。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

57

主题

431

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
886
金钱
886
注册时间
2011-12-25
在线时间
12 小时
发表于 2013-9-14 11:19:29 | 显示全部楼层
国内RTOS实在太多了。。RTT现在发展不错。。呵呵。。楼主强。。
很喜爱电子行业
回复 支持 反对

使用道具 举报

1

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2013-9-28
在线时间
21 小时
发表于 2013-10-8 22:22:28 | 显示全部楼层
谢谢分享。。。
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
28
金钱
28
注册时间
2015-9-14
在线时间
0 小时
发表于 2015-9-25 10:27:57 | 显示全部楼层
楼主你好, 关于printf 重定向的问题: 我用arm-none-eabi-gcc如何实现呢? 
你的代码里面用ARMCC编译运行没有问题,但是我用arm-none-eabi-gcc编译时就会报错(开发需要我们是在linux里面编译的),
是编译选项的问题还是重定向函数的问题呢? 貌似armcc和arm-gcc的printf的实现机制是不一样的。
可以得话,楼住是否能够提供一个简单的arm-none-eabi-gcc模板,感激不尽!!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 01:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表