在官方例子基础上改的。
使用串口空闲中断可以接收小于接收缓冲区数量的数据。
接收和发送全都通过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[] = "
USART Example:USART-Hyperterminal communication using DMA.
Enter your Text
";
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);
}
******************************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接收模式
}
}
一周热门 更多>