注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题

chenht7的个人空间 http://home.eeworld.com.cn/space-uid-490705.html [收藏] [复制] [分享] [RSS]

日志

学STM8-3-程序-Usart_20180112

已有 443 次阅读2018-1-12 10:42 |个人分类:STM8

 学STM8-3-程序-Usart
---
2018/1/12

# 一、内容概述  
## 1.1 主要功能
这次的串口通讯的功能实现,貌似很难能够再在核心板上进行实际的效果显示了。而且也还没买RS2323芯片组成的模块,也就很难能看到实际的效果。so就分析分析下程序好了。以及参考下自己前阵子学的这个STM32的知识来进行。
具体需要实现的功能描述:
1. 通过将字符串“硬件平台为:”,“STM8 开发板”打印到电脑上。

## 1.2 整体框架

[整体框图]

# 二、开发环境  
## 2.1 开发环境
开发环境,采用了IAR进行开发。并且目前所用的下载器和仿真器为ST-Link。而使用的硬件板子,为外购的开发核心板。
其中的那个将单片机信息传输给电脑所用的USART芯片采用了RS2323。
单片机型号:STM8S103F3P6
模块电路:RS2323转串口电路

## 2.2 硬件连接

[RS2323连接图]

目前的硬件连接方式为:
输入引脚:无

输出引脚:
RS2323的TX -- PD5(UART1_TX)
RS2323的RX -- PD6(UART1_RX)

# 三、库

## 3.1 调用的系统库
库的调用,需要根据实际的实验要求来进行。在这个实验中,
需要进行数据的输入和输出的功能 <-- 调用GPIO库
系统需要正常运行 <-- 调用时钟管理的CLK库
串口数据传输所用 <-- 调用串口库UART1库

## 3.2 自编的库

自己需要进行编写的库为两个方面。
一个是关于中断信号的处理 <-- 修改中断库stm8s_interruput.c
一个是关于异步通讯时功能所用 <-- uart.c
主控 <-- 也就是写个main.c,这应该不算是库文件,但也是需要自己编写的了。

# 四、函数
## 4.1 说明
程序内容变大了,只能说,是应该要稍微精简一下内容了。

## 4.2 main.c
备份数据的寄存器。可以用来写入用户数据。

[main流程图]

```
#include "stm8s.h"       // 关于所用到的芯片
#include "stm8s_clk.h"   // 时钟的库
#include "intrinsics.h"  // 中断的库
#include "stm8s_uart1.h" // 串口处理库
#include "uart.h"        // 自编的通讯时信息

void Delay(u32 nCount);  // 延时函数
extern u8 RxBuffer[RxBufferSize];  // 接收时缓冲
extern u8 UART_RX_NUM;             // 接收的信息

int main(void)
{
   u8 len ;
  /* Infinite loop */
  
  /*设置内部时钟16M为主时钟*/
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
  /*!<Set High speed internal clock  */

   Uart_Init();           // 串口初始化
   __enable_interrupt();  // 中断使能
   printf("\r\n硬件平台为:%s\r\n","iCreate STM8 开发板");  // 采用重定义发送数据
   
   //另一种发送方法
   UART1_SendString("Serial Communication ---STM8 Development Board of FengChi Electron ",\
             sizeof("Serial Communication ---STM8 Development Board of FengChi Electron"));
   Delay(0xffff);
   UART1_SendByte('\n');
   Delay(0xffff);
   while (1)
   {
      if(UART_RX_NUM&0x80)
      {
        len=UART_RX_NUM&0x3f;/*得到此次接收到的数据长度*/
        UART1_SendString("You sent the messages is:",sizeof("You sent the messages is"));
        UART1_SendString(RxBuffer,len);
        UART1_SendByte('\n');
        UART_RX_NUM=0;
      }
    }  
}

// 延时函数
void Delay(u32 nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {
    nCount--;
  }
}

```


## 4.3 uart
### 4.3.1 uart.h
这个库主要作为为对于一些信息进行预定义。

```
#ifndef __UART_H
#define __UART_H
#include "stm8s.h"
#include <stdio.h>

#define countof(a)   (sizeof(a) / sizeof(*(a)))
#define RxBufferSize 64

void Uart_Init(void);    // 串口初始化
void UART1_SendByte(u8 data);  // 数据发送
int fputc(int ch, FILE *f);    // 重定向函数
void UART1_SendString(u8* Data,u16 len);  // 字符串发送函数
u8 UART1_ReceiveByte(void);    // 数据接收函数
void USART1_printf( uint8_t *Data,...);  // 串口输出函数
#endif

```

### 4.3.2 uart.c

```
void Uart_Init(void)
{
    // 这个初始化的过程为UART1复位-->初始化-->配置中断-->启用中断
    UART1_DeInit();
    UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, \
    UART1_PARITY_NO , UART1_SYNCMODE_CLOCK_DISABLE , UART1_MODE_TXRX_ENABLE);
    UART1_ITConfig(UART1_IT_RXNE_OR,ENABLE  );
    UART1_Cmd(ENABLE );
}

void UART1_SendByte(u8 data)
{
    // 数据发送函数,过程为发送8位数据-->发送完毕
    UART1_SendData8((unsigned char)data);
    /* Loop until the end of transmission */
    while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
}

// 发送多组数据
void UART1_SendString(u8* Data,u16 len)
{
  u16 i=0;
  for(;i<len;i++)
    UART1_SendByte(Data[i]);
}

// 数据接收函数
u8 UART1_ReceiveByte(void)
{
     u8 USART1_RX_BUF;  // 设置数据的缓存 
     while (UART1_GetFlagStatus(UART1_FLAG_RXNE) == RESET);  // 当数据寄存器不为空
     USART1_RX_BUF=UART1_ReceiveData8();  // 数据进行接收
     return  USART1_RX_BUF;  // 返回接收的串口数据
}

/*
 * 函数名:fputc
 * 描述  :重定向c库函数printf到USART1
 * 输入  :无
 * 输出  :无
 * 调用  :由printf调用
 */
int fputc(int ch, FILE *f)
{  
/* 将Printf内容发往串口 */
  UART1_SendData8((unsigned char) ch);    // 数据发送
  while (!(UART1->SR & UART1_FLAG_TXE));  // 判断串口的溢出位
 
  return (ch);
}

/********************************************************
 * 函数名:itoa
 * 描述  :将整形数据转换成字符串
 * 输入  :-radix =10 表示10进制,其他结果为0
 *         -value 要转换的整形数
 *         -buf 转换后的字符串
 *         -radix = 10
 * 输出  :无
 * 返回  :无
 * 调用  :被USART1_printf()调用
 *******************************************************/
static char *itoa(int value, char *string, int radix)
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;

    /* This implementation only works for decimal numbers. */
    // 只针对十进制的,如果不是10进制,则进行输出输入数据
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }

    // 判断数据是否发送完毕
    if (!value)
    {
        *ptr++ = 0x30; //把这个地址(0x30)赋给指针变量(*ptr[])的下一个地址,然后ptr[1]的内容就变成0x30这个地址了
        //主要是针对于ASCII码,ASCII码中,1-9,以及A-Z这些都是从0x30中开始
        *ptr = 0;      //对目前的指针变量中的数值进行清零
        return string;
    }

    /* if this is a negative value insert the minus sign. */
    if (value < 0)
    {
        *ptr++ = '-';

        /* Make the value positive. */
        value *= -1;
    }

    //判断循环的次数,相对于将数据小于10000的数据,进行按位进行发送
    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;
        if (d || flag)    //判断数据有无发送完毕,标志位和数据位的情况
        {
            *ptr++ = (char)(d + 0x30);  //将数字转换为ASCII码
            value -= (d * i);    //数据进行重新恢复
            flag = 1;
        }
    }

    /* Null terminate the string. */
    *ptr = 0;

    return string;

} /* NCL_Itoa */

/************************************************************************
 * 函数名:USART1_printf
 * 描述  :格式化输出,类似于C库中的printf,但这里没有用到C库
 * 输入  :-USARTx 串口通道,这里只用到了串口1,即USART1
 *             -Data   要发送到串口的内容的指针
 *               -...    其他参数
 * 输出  :无
 * 返回  :无 
 * 调用  :外部调用
 *         典型应用USART1_printf( "\r\n this is a demo \r\n" );
 *                     USART1_printf(  "\r\n %d \r\n", i );
 *                     USART1_printf(  "\r\n %s \r\n", j );
 ***************************************************************************/
void USART1_printf( uint8_t *Data,...)
{
  const char *s;
  int d;   
  char buf[16];
  va_list ap;
  va_start(ap, Data);

  while ( *Data != 0)     // 判断是否到达字符串结束符
  {                                          
      if ( *Data == 0x5c )  //'\',参见ASCII码,因为这是转义字符没办法
      {                                      
              switch ( *++Data )
              {
                      case 'r':                                      //回车符,见ASCII码
                              UART1_SendData8(0x0d);
                              Data ++;
                              break;

                      case 'n':                                      //换行符
                              UART1_SendData8(0x0a);    
                              Data ++;
                              break;
                      
                      default:
                              Data ++;
                          break;
              }             
      }
      else if ( *Data == '%')    //判断数据的情况
      {                    //
        switch ( *++Data )       //指向下一个数据组
        {                
          case 's':                        //字符串
          s = va_arg(ap, const char *);
          for ( ; *s; s++)       // 发送字符串
           {
             UART1_SendData8(*s);
             while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
           }
          Data++;
          break;

          case 'd':    //十进制
          d = va_arg(ap, int);
          itoa(d, buf, 10);
          for (s = buf; *s; s++) 
           {
             UART1_SendData8(*s);
             while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
           }
           Data++;
           break;
          default:
             Data++;
             break;
          }         
     } /* end of else if */
    else UART1_SendData8(*Data++);
    while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);    //直到数据发送完毕
  }
}

```


## 4.4 stm8s_interrupt
### 4.4.1 stm8s_interrupt.c

需要选对自己的中断类型,从而在库文件中进行对应的修改。比如这次所使用的中断为异步通讯中断。

```

__interrupt void UART1_RX_IRQHandler(void)

   u8 Res;
    if(UART1_GetITStatus(UART1_IT_RXNE )!= RESET)  
    {/*接收中断(接收到的数据必须是0x0d 0x0a结尾)*/
    Res =UART1_ReceiveData8();
        /*(USART1->DR);读取接收到的数据,当读完数据后自动取消RXNE的中断标志位*/
    if((UART_RX_NUM&0x80)==0)/*接收未完成*/
      {
        if(UART_RX_NUM&0x40)/*接收到了0x0d,即回车*/
        {
          if(Res!=0x0a) UART_RX_NUM=0;/*接收错误,重新开始*/
          else  UART_RX_NUM|=0x80;    /*接收完成了 */
        }
            else /*还没收到0X0D*/
              {    
                if(Res==0x0d) UART_RX_NUM|=0x40;
                else
                  {
                    RxBuffer[ UART_RX_NUM&0X3F]=Res ;
                     UART_RX_NUM++;
                      if( UART_RX_NUM>63) UART_RX_NUM=0;/*接收数据错误,重新开始接收*/  
                  }         
               }
      }           
    }  
}

```


# 五、实际效果
我在实际的时候,采用了一个用CH340来搭建的USB信号转TTL信号的转换,从而使得电脑串口软件与芯片进直接的通讯,没用到这个RS232的信号。诶,穷啊,232信号的东西还没买。等以后有用了再搞个吧。


# 六、总结
这个项目因为自己手头少了一个RS2323的芯片,从而无法进行一个实际效果的证明,也只能是注释注释程序来进行学习吧。
其中大部分的这个内容,在我自己学32中的内容时,基本上一模一样,连这个数据转换,以及重定向的函数都是一样的。


# 参考资料
[1] 风驰iCreate嵌入式开发工作室,LED的开发文件.  
[2] 《STM8S库函数中文参考 v1.0》, BH7KQK  
[3] ST公司,《RM0016 参考手册,STM8S微控制器家族》[M].
[4] ST公司,《Access line, 16 MHz STM8S 8-bit MCU, up to 8 Kbytes Flash, data
EEPROM,10-bit ADC, 3 timers, UART, SPI, I2C》
[5] 野火团队,《零死角玩转STM32》[M].  

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

小黑屋|手机版|Archiver|电子工程世界 ( 京ICP证 060456

GMT+8, 2018-4-21 01:58 , Processed in 0.017150 second(s), 11 queries , Redis On.

Powered by EEWORLD电子工程世界

© 2018 http://bbs.eeworld.com.cn/

返回顶部