本帖最后由 pzljun 于 2021-4-14 02:02 编辑
#技术资源# #申请原创# 此码来自官方例程,clk_sync_dma_tx.
源同步初使化发送错误,故改成异步发送。经修改,已能实现功能。其官方例程写了很多误导人的东西
/*******************************************************************************
* Copyright (C) 2016, Huada Semiconductor Co., Ltd. All rights reserved.
*
* This software is owned and published by:
* Huada Semiconductor Co., Ltd. ("HDSC").
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with HDSC
* components. This software is licensed by HDSC to be adapted only
* for use in systems utilizing HDSC components. HDSC shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. HDSC is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* Disclaimer:
* HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
* REGARDING THE SOFTWARE (INCLUDING ANY ACCOMPANYING WRITTEN MATERIALS),
* ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
* WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
* WARRANTY OF NONINFRINGEMENT.
* HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
* NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
* LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
* INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
* SAVINGS OR PROFITS,
* EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
* INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
* FROM, THE SOFTWARE.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/
/******************************************************************************/
/** \file main.c
**
** \brief This sample demonstrates clock sync data receive and transfer by DMA.
**
** - 2018-11-27 1.0 Hongjh First version for Device Driver Library of USART
**
******************************************************************************/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ddl.h"
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/**
*******************************************************************************
** \brief buffer handle
**
******************************************************************************/
typedef struct stc_buf_handle
{
uint8_t u8Size;
uint8_t au8Buf[200];
} stc_buf_handle_t;
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/* DMAC */
#define DMA_UNIT (M4_DMA1)
#define DMA_CH (DmaCh0)
#define DMA_TRG_SEL (EVT_USART3_TI) //此处修为3,根据硬件来的
/* USART channel definition */
#define USART_CH (M4_USART3) //此处修为3,根据硬件来的
/* USART baudrate definition */
#define USART_BAUDRATE (256000ul) //此处修为25600,串口助手没300000
/* USART TX Port/Pin definition */
#define USART_TX_PORT (PortH)
#define USART_TX_PIN (Pin02) //此处修为H2,根据硬件来的
#define USART_TX_FUNC (Func_Usart3_Tx)
/* USART CK Port/Pin definition */
#define USART_CK_PORT (PortD)
#define USART_CK_PIN (Pin07)
#define USART_CK_FUNC (Func_Usart_Ck)
/* DMA block transfer complete interrupt */
#define DMA_BTC_INT_NUM (INT_DMA1_TC0) //此处要修改
#define DMA_BTC_INT_IRQn (Int002_IRQn)
/* LED(D26: green color) Port/Pin definition */
#define LED_PORT (PortA)
#define LED_PIN (Pin07)
/* LED operation */
#define LED_ON() (PORT_SetBits(LED_PORT, LED_PIN))
#define LED_OFF() (PORT_ResetBits(LED_PORT, LED_PIN))
/* User key:SW2 Port/Pin definition */
#define KEY_PORT (PortD)
#define KEY_PIN (Pin03)
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
static void ClkInit(void);
static void LedInit(void);
static void DmaInit(void);
static void DmaBtcIrqCallback(void);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
static stc_buf_handle_t m_stcTxBufHanlde;
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
*******************************************************************************
** \brief Initialize Clock.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void ClkInit(void)
{
stc_clk_xtal_cfg_t stcXtalCfg;
stc_clk_mpll_cfg_t stcMpllCfg;
en_clk_sys_source_t enSysClkSrc;
stc_clk_sysclk_cfg_t stcSysClkCfg;
MEM_ZERO_STRUCT(enSysClkSrc);
MEM_ZERO_STRUCT(stcSysClkCfg);
MEM_ZERO_STRUCT(stcXtalCfg);
MEM_ZERO_STRUCT(stcMpllCfg);
/* Set bus clk div. */
stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;
stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
CLK_SysClkConfig(&stcSysClkCfg);
/* Switch system clock source to MPLL. */
/* Use Xtal as MPLL source. */
stcXtalCfg.enMode = ClkXtalModeOsc;
stcXtalCfg.enDrv = ClkXtalLowDrv;
stcXtalCfg.enFastStartup = Enable;
CLK_XtalConfig(&stcXtalCfg);
CLK_XtalCmd(Enable);
/* MPLL config. */
stcMpllCfg.pllmDiv = 1u; /* XTAL 8M / 1 */
stcMpllCfg.plln = 50u; /* 8M*50 = 400M */
stcMpllCfg.PllpDiv = 4u; /* MLLP = 100M */
stcMpllCfg.PllqDiv = 4u; /* MLLQ = 100M */
stcMpllCfg.PllrDiv = 4u; /* MLLR = 100M */
CLK_SetPllSource(ClkPllSrcXTAL);
CLK_MpllConfig(&stcMpllCfg);
/* flash read wait cycle setting */
EFM_Unlock();
EFM_SetLatency(EFM_LATENCY_4);
EFM_Lock();
/* Enable MPLL. */
CLK_MpllCmd(Enable);
/* Wait MPLL ready. */
while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
{
}
/* Switch system clock source to MPLL. */
CLK_SetSysClkSource(CLKSysSrcMPLL);
}
/**
*******************************************************************************
** \brief Initialize LED.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void LedInit(void)
{
stc_port_init_t stcPortInit;
LED_OFF();
/* LED Port/Pin initialization */
MEM_ZERO_STRUCT(stcPortInit);
stcPortInit.enPinMode = Pin_Mode_Out;
stcPortInit.enExInt = Enable;
stcPortInit.enPullUp = Enable;
PORT_Init(LED_PORT, LED_PIN, &stcPortInit);
}
/**
*******************************************************************************
** \brief Initialize DMA.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
static void DmaInit(void)
{
stc_dma_config_t stcDmaInit;
stc_irq_regi_conf_t stcIrqRegiCfg;
/* Enable peripheral clock */
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1 | PWC_FCG0_PERIPH_DMA2,Enable);
/* Enable DMA. */
DMA_Cmd(DMA_UNIT,Enable);
/* Initialize DMA. */
MEM_ZERO_STRUCT(stcDmaInit);
stcDmaInit.u16BlockSize = 1u; /* 1 block */
stcDmaInit.u16TransferCnt = 10;//(uint16_t)m_stcTxBufHanlde.u8Size;/* Transfer count */
/*此为修改语句,一次就发10个*/
stcDmaInit.u32SrcAddr = (uint32_t)(m_stcTxBufHanlde.au8Buf); /* Set source address. */
stcDmaInit.u32DesAddr = (uint32_t)(&USART_CH->DR); /* Set destination address. */
stcDmaInit.stcDmaChCfg.enSrcInc = AddressIncrease; /* Set source address mode. */
stcDmaInit.stcDmaChCfg.enDesInc = AddressFix; /* Set destination address mode. */
stcDmaInit.stcDmaChCfg.enIntEn = Enable; /* Enable interrupt. */
stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit; /* Set data width 8bit. */
DMA_InitChannel(DMA_UNIT, DMA_CH, &stcDmaInit);
/* Enable the specified DMA channel. */
DMA_ChannelCmd(DMA_UNIT, DMA_CH, Enable);
/* Clear DMA flag. */
DMA_ClearIrqFlag(DMA_UNIT, DMA_CH, TrnCpltIrq);
/* Enable peripheral circuit trigger function. */
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS,Enable);
/* Set DMA trigger source. */
DMA_SetTriggerSrc(DMA_UNIT, DMA_CH, DMA_TRG_SEL);
/* Set DMA block transfer complete IRQ */
stcIrqRegiCfg.enIRQn = DMA_BTC_INT_IRQn;
stcIrqRegiCfg.pfnCallback = &DmaBtcIrqCallback;
stcIrqRegiCfg.enIntSrc = DMA_BTC_INT_NUM;
enIrqRegistration(&stcIrqRegiCfg);
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
}
/**
*******************************************************************************
** \brief DMA block transfer complete irq callback function.
**
** \param [in] None
**
** \retval None
**
******************************************************************************/
volatile const uint8_t BT1[10]={0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9};
volatile const uint8_t BT2[10]={0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9};
volatile const uint8_t BT3[10]={0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9};
volatile uint8_t **;
static void DmaBtcIrqCallback(void)
{
DMA_ClearIrqFlag(DMA_UNIT, DMA_CH, TrnCpltIrq); //此处要修改
** = 0; /*此为增加语句*/
}
void DmaTest(uint8_t ch)
{ uint8_t i;
while(1)
{ if(**==0)break;
}; //只有标志位改成0才会写下一条
if(**==0)
{ //DMA发送会自动使能清0 DMA_ChannelCmd(DMA_UNIT, DMA_CH, Disable);
** = 1;
DMA_SetSrcAddress(DMA_UNIT, DMA_CH,(uint32_t)(m_stcTxBufHanlde.au8Buf));
DMA_SetTransferCnt(DMA_UNIT, DMA_CH,10);
// DMA_ChannelCmd(DMA_UNIT, DMA_CH, Enable);
if(ch==0)
{ for(i=0;i<10;i++){m_stcTxBufHanlde.au8Buf = BT1;}
}
if(ch==1)
{ for(i=0;i<10;i++){m_stcTxBufHanlde.au8Buf = BT2;}
}
if(ch==2)
{ for(i=0;i<10;i++){m_stcTxBufHanlde.au8Buf = BT3;}
}
// DMA_SetSrcAddress(DMA_UNIT, DMA_CH,(uint32_t)(m_stcTxBufHanlde.au8Buf));
// DMA_SetTransferCnt(DMA_UNIT, DMA_CH,10);
DMA_ChannelCmd(DMA_UNIT, DMA_CH, Enable);
if(ch==0) USART_SendData(M4_USART3,BT1[0]); //触发发送2
if(ch==1) USART_SendData(M4_USART3,BT2[0]); //触发发送3
if(ch==2) USART_SendData(M4_USART3,BT3[0]); //触发发送1,不写不会发送
}
}
/**
*******************************************************************************
** \brief Main function of project
**
** \param None
**
** \retval int32_t return value, if needed
**
******************************************************************************/
int32_t main(void)
{
uint8_t i;
en_result_t enRet = Ok;
uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \
PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;
/* const stc_usart_clksync_init_t stcInitCfg = {
UsartIntClkCkOutput,
UsartClkDiv_1,
UsartDataLsbFirst,
UsartRtsEnable,
}; 原程序不能用,否则串口输出值不正确
*/
const stc_usart_uart_init_t stcInitCfg = {
UsartIntClkCkNoOutput,
UsartClkDiv_1,
UsartDataBits8,
UsartDataLsbFirst,
UsartOneStopBit,
UsartParityNone,
UsartSamleBit8,
UsartStartBitFallEdge,
UsartRtsEnable,
};
enRet = USART_UART_Init(USART_CH, &stcInitCfg);
/* Initialize buffer */
m_stcTxBufHanlde.u8Size = (uint8_t)sizeof(m_stcTxBufHanlde.au8Buf);
for (i = 0u; i < m_stcTxBufHanlde.u8Size; i++)
{
m_stcTxBufHanlde.au8Buf = i;
}
/* Initialize Clock */
ClkInit();
/* Initialize LED */
LedInit();
/* Initialize DMA */
DmaInit();
/* Enable peripheral clock */
PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);
/* Initialize USART IO */
PORT_SetFunc(USART_CK_PORT, USART_CK_PIN, USART_CK_FUNC, Disable);
PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);
/* Initialize Clock sync */
/*原程序不能用*/// enRet = USART_CLKSYNC_Init(USART_CH, &stcInitCfg);
if (enRet != Ok)
{
while (1)
{
}
}
/* Set baudrate */
enRet = USART_SetBaudrate(USART_CH, USART_BAUDRATE);
if (enRet != Ok)
{
while (1)
{
}
}
/* User key : SW2 */
while (Reset != PORT_GetBit(KEY_PORT, KEY_PIN))
{
}
/*Enable TX interupt function*/
USART_FuncCmd(USART_CH, UsartTxAndTxEmptyInt, Enable);
while (1)
{
if (Set == DMA_GetIrqFlag(DMA_UNIT, DMA_CH, TrnCpltIrq))
{
LED_ON(); /* Send completely */
}
DmaTest(0);
DmaTest(1);
DmaTest(2);
}
}
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/
|
共1人点赞
|
验证了一下代码,确实可以。但是第一 个字节会发送2次。修改DMA源地址从数组的buf[1]开始,并且DMA传输长度减1,发送就正常了。