搜索
bottom↓
回复: 4

发个 STM8L的 USART DMA 可变长发送接收,使用串口空闲

[复制链接]

出0入0汤圆

发表于 2017-8-7 15:03:57 | 显示全部楼层 |阅读模式
在官方例子基础上改的。
使用串口空闲中断可以接收小于接收缓冲区数量的数据。
接收和发送全都通过DMA。

*************************main**********************************

#include "stm8l15x.h"

#define USART_DMA_CHANNEL_RX   DMA1_Channel2
#define USART_DMA_CHANNEL_TX   DMA1_Channel1
#define USART_DMA_FLAG_TCRX    (uint16_t)DMA1_FLAG_TC2
#define USART_DMA_FLAG_TCTX    (uint16_t)DMA1_FLAG_TC1
#define USART_DR_ADDRESS       (uint16_t)0x5231  /* USART1 Data register Address */

#define USART_BAUDRATE         (uint32_t)9600
#define DATA_TO_TRANSFER       (countof(TxBuffer) - 1)
#define DATA_TO_RECEIVE        (uint8_t) 0x20      //这个值要设的比最多可能的值大一些
#define countof(a)            (sizeof(a) / sizeof(*(a)))

#define LED1_PORT GPIOE
#define LED1_PIN  GPIO_Pin_7
#define KEY_PORT  GPIOD
#define KEY_PIN   GPIO_Pin_1
#define KEY_DOWN  GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == RESET

uint8_t TxBuffer[] = "\n\rUSART Example:USART-Hyperterminal communication using DMA.\nEnter your Text\n\r";
uint8_t RxBuffer[DATA_TO_RECEIVE] = {0};

bool TX_DMA_READY_FLG = FALSE;
bool TX_DMA_ENABLE_FLG = FALSE;
unsigned char RxDMADatCount = 0;
unsigned char RxRECCount = 0;
/* Private function prototypes -----------------------------------------------*/
static void CLK_Config(void);
static void DMA_Config(void);
void Delay (uint32_t nCount);
void LEDToggle(void);
/* Private functions ---------------------------------------------------------*/

void Set_485(void);

void DMA_START_TX(void);
void DMA_START_RX(void);


static void CLK_Config(void)
{
  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
  CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, ENABLE);
}

void main(void)
{
  CLK_Config();
  GPIO_Init(LED1_PORT,LED1_PIN,GPIO_Mode_Out_PP_Low_Slow);
  GPIO_Init(KEY_PORT,KEY_PIN,GPIO_Mode_In_PU_No_IT);
  Set_485();
  DMA_Config();
  TX_DMA_READY_FLG  = TRUE;
  enableInterrupts();
  USART_Cmd(USART1, ENABLE);

  
    while (1)
  {
   if(KEY_DOWN)TX_DMA_ENABLE_FLG = TRUE;else TX_DMA_ENABLE_FLG = FALSE;//按键以后开始DMA发送
    Delay((uint32_t)0xFFF); //模拟CPU在处理某些事务
   if(TX_DMA_READY_FLG && TX_DMA_ENABLE_FLG)
   {
    TX_DMA_READY_FLG = FALSE;//在DMA-TC中断中会将此置 true 后改为按键发动
    DMA_START_TX();//开启TX_DMA发送数据
    LEDToggle();//翻转LED灯
   }
   RxRECCount =DATA_TO_RECEIVE - RxDMADatCount;//接收到的数据个数,用总的接收区减去DMA接收后还余下未接受的个数

  }
}


static void DMA_Config(void)
{
  /* Deinitialize DMA channels */
  DMA_GlobalDeInit();

  DMA_DeInit(DMA1_Channel1);
  DMA_DeInit(DMA1_Channel2);

  /* DMA channel Rx of USART Configuration */
  DMA_Init(USART_DMA_CHANNEL_RX, (uint16_t)RxBuffer, (uint16_t)USART_DR_ADDRESS,
           DATA_TO_RECEIVE, DMA_DIR_PeripheralToMemory, DMA_Mode_Normal,
           DMA_MemoryIncMode_Inc, DMA_Priority_Low, DMA_MemoryDataSize_Byte);

  /* DMA channel Tx of USART Configuration */
  DMA_Init(USART_DMA_CHANNEL_TX, (uint16_t)TxBuffer, (uint16_t)USART_DR_ADDRESS,
           DATA_TO_TRANSFER, DMA_DIR_MemoryToPeripheral, DMA_Mode_Normal,
           DMA_MemoryIncMode_Inc, DMA_Priority_High, DMA_MemoryDataSize_Byte);

  /* Enable the USART Tx/Rx DMA requests */
  USART_DMACmd(USART1, USART_DMAReq_TX, ENABLE);
  USART_DMACmd(USART1, USART_DMAReq_RX, ENABLE);

   DMA_ITConfig(USART_DMA_CHANNEL_TX, DMA_ITx_TC, ENABLE);//使能TC中断
  
  /* Global DMA Enable */
  DMA_GlobalCmd(ENABLE);

  /* Enable the USART Tx DMA channel */
// DMA_Cmd(USART_DMA_CHANNEL_TX, ENABLE);
  /* Enable the USART Rx DMA channel */
  //DMA_Cmd(USART_DMA_CHANNEL_RX, ENABLE);         
}

void Set_485(void)
{
  GPIO_Init( GPIOC, GPIO_Pin_4, GPIO_Mode_Out_PP_High_Fast);
  GPIO_ResetBits(GPIOC, GPIO_Pin_4);

  CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);

  GPIO_ExternalPullUpConfig(GPIOC, GPIO_Pin_2 | GPIO_Pin_3, ENABLE);

  USART_DeInit(USART1);

  USART_Init(USART1, (uint32_t)9600, USART_WordLength_8b, USART_StopBits_1,
             USART_Parity_No, (USART_Mode_TypeDef)(USART_Mode_Rx | USART_Mode_Tx));

  USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
  
  USART_Cmd(USART1, DISABLE);

}

void Delay(uint32_t nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {
    nCount--;
  }
}
void LEDToggle(void)
{
  GPIO_ToggleBits(LED1_PORT,LED1_PIN);
}

void DMA_START_TX(void)
{
   DMA_Cmd(USART_DMA_CHANNEL_TX, DISABLE);
   DMA_ClearFlag(DMA1_FLAG_TC1);
   DMA_ClearFlag(DMA1_FLAG_HT1);
   DMA_SetCurrDataCounter(USART_DMA_CHANNEL_TX, DATA_TO_TRANSFER);
   DMA_Cmd(USART_DMA_CHANNEL_TX, ENABLE);
}
void DMA_START_RX(void)
{   DMA_ClearFlag(DMA1_FLAG_TC2);
    DMA_ClearFlag(DMA1_FLAG_HT2);
    DMA_Cmd(USART_DMA_CHANNEL_RX, DISABLE);
    DMA_SetCurrDataCounter(USART_DMA_CHANNEL_RX, DATA_TO_RECEIVE);
    DMA_Cmd(USART_DMA_CHANNEL_RX, ENABLE);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2017-8-7 15:04:33 | 显示全部楼层
本帖最后由 lovepig200 于 2017-8-7 15:06 编辑

******************************it.c*************************************

/* Includes ------------------------------------------------------------------*/
#include "stm8l15x_it.h"
   
   
   
   
extern void DMA_START_RX(void);
extern void LEDToggle();
extern void DMA_START_TX();
extern bool TX_DMA_READY_FLG;
extern unsigned char RxDMADatCount;
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/

#ifdef _COSMIC_
/**
  * @brief Dummy interrupt routine
  * @param  None
  * @retval None
  */
INTERRUPT_HANDLER(NonHandledInterrupt, 0)
{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
}
#endif

/**
  * @brief TRAP interrupt routine
  * @param  None
  * @retval None
  */
INTERRUPT_HANDLER_TRAP(TRAP_IRQHandler)
{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
}


INTERRUPT_HANDLER(DMA1_CHANNEL0_1_IRQHandler, 2)
{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
  TX_DMA_READY_FLG = TRUE; //TC传送完成后,置位READY
  DMA_ClearITPendingBit(DMA1_IT_TC1);
}

INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler, 28)
{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
if(USART_GetITStatus(USART1,  USART_IT_IDLE) != RESET)
{
unsigned char temp;
temp = USART1->SR;temp = USART1->DR;//IDLE清零需要依次读SR 和DR 寄存器
USART_ClearITPendingBit(USART1,  USART_IT_IDLE);
RxDMADatCount =  DMA_GetCurrDataCounter(DMA1_Channel2);
DMA_START_RX();//重新开启串口DMA接收模式
}
}

出0入0汤圆

发表于 2017-8-7 17:11:06 | 显示全部楼层
STM8 DMA 看看

出0入0汤圆

发表于 2017-8-7 20:32:10 来自手机 | 显示全部楼层
串口空闲,怕不怕不够长

出0入0汤圆

发表于 2017-8-7 21:56:37 | 显示全部楼层
帮顶下,这几天在弄stm8l15x的串口中断可变长收发
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-17 23:41

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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