专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
寻找基于HAL库的I2S历程
2019-07-20 19:58
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
2401
7
1730
由于项目的需要,目前要在F429上用到2个I2S和一个SAI接口。SAI接口已经参考阿波罗的历程调试好了,目前需要把429上2个I2S接口也初始化成功(不是通过SAI配置成I2S格式,而是单独初始化2个I2S)看了HAL库,不太清楚要处理哪些,所以需要基于HAL库的I2S历程。
请大家提供链接或者分享一下代码,万分感谢!
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
襟铭心缘
1楼-- · 2019-07-20 23:56
本帖最后由 襟铭心缘 于 2016-9-19 16:07 编辑
我的其实配置的没问题,就是在中断函数出的问题,现在已经解决了,可以正常播放音乐。
[mw_shl_code=c,true]#include "bsp_i2s.h"
#include "delay.h"
I2S_HandleTypeDef I2S_Handle;
DMA_HandleTypeDef I2S_TxDMA_Handle;
//开启I2S2的DMA功能,HAL库没有提供此函数
//因此我们需要自己操作寄存器编写一个
void I2S2_DMA_Enable(void)
{
u32 tempreg=0;
tempreg=SPI2->CR2; //先读出以前的设置
tempreg|=SPI_CR2_TXDMAEN; //使能DMA
SPI2->CR2=tempreg; //写入CR1寄存器中
}
void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
GPIO_Initure.Pin=GPIO_PIN_12;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_2;
GPIO_Initure.Alternate=GPIO_AF6_I2S2ext;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_6;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_3;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOD,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_3;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOI,&GPIO_Initure);
}
//参数I2S_Mode: @ref SPI_I2S_Mode I2S_MODE_SLAVE_TX:从机发送;I2S_MODE_SLAVE_RX:从机接收;I2S_MODE_MASTER_TX:主机发送;I2S_MODE_MASTER_RX:主机接收;
//参数I2S_DataFormat: @ref SPI_I2S_Data_Format :数据长度,I2S_DATAFORMAT_16B,16位标准;I2S_DATAFORMAT_16B_EXTENDED,16位扩展(frame=32bit);I2S_DATAFORMAT_24B,24位;I2S_DATAFORMAT_32B,32位.
void I2S2_Init(u16 I2S_Mode,u16 I2S_DataFormat)
{
I2S_Handle.Instance=SPI2;
__HAL_I2S_DISABLE(&I2S_Handle);
I2S_Handle.Init.Mode=I2S_Mode;
I2S_Handle.Init.Standard=I2S_STANDARD_PHILIPS;
I2S_Handle.Init.DataFormat=I2S_DataFormat;
I2S_Handle.Init.MCLKOutput=I2S_MCLKOUTPUT_ENABLE;
I2S_Handle.Init.AudioFreq=I2S_AUDIOFREQ_DEFAULT;
I2S_Handle.Init.CPOL=I2S_CPOL_LOW;
I2S_Handle.Init.ClockSource=I2S_CLOCK_PLL;
if(HAL_I2S_GetState(&I2S_Handle) == HAL_I2S_STATE_RESET)
{
HAL_I2S_MspInit(&I2S_Handle);
}
HAL_I2S_Init(&I2S_Handle);
__HAL_I2S_ENABLE(&I2S_Handle);
I2S2_DMA_Enable();
}
//采样率计算公式:Fs=I2SxCLK/[256*(2*I2SDIV+ODD)]
//I2SxCLK=(HSE/pllm)*PLLI2SN/PLLI2SR
//一般HSE=25Mhz
//pllm:在Sys_Clock_Set设置的时候确定,一般是8
//PLLI2SN:一般是192~432
//PLLI2SR:2~7
//I2SDIV:2~255
//ODD:0/1
//I2S分频系数表@pllm=25,HSE=25Mhz,即vco输入频率为1Mhz
//表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
const u16 I2S_PSC_TBL[][5]=
{
{800 ,256,5,12,1}, //8Khz采样率
{1102,429,4,19,0}, //11.025Khz采样率
{1600,213,2,13,0}, //16Khz采样率
{2205,429,4, 9,1}, //22.05Khz采样率
{3200,213,2, 6,1}, //32Khz采样率
{4410,271,2, 6,0}, //44.1Khz采样率
{4800,258,3, 3,1}, //48Khz采样率
{8820,316,2, 3,1}, //88.2Khz采样率
{9600,344,2, 3,1}, //96Khz采样率
{17640,361,2,2,0}, //176.4Khz采样率
{19200,393,2,2,0}, //192Khz采样率
};
//设置IIS的采样率(@MCKEN)
//samplerate:采样率,单位:Hz
//返回值:0,设置成功;1,无法设置.
u8 I2S2_SampleRate_Set(u32 samplerate)
{
u8 i=0;
u32 tempreg=0;
samplerate/=10;//缩小10倍
for(i=0;i<(sizeof(I2S_PSC_TBL)/10);i++)//看看改采样率是否可以支持
{
if(samplerate==I2S_PSC_TBL
[0])break;
}
__HAL_RCC_PLLI2S_DISABLE();
if(i==(sizeof(I2S_PSC_TBL)/10))return 1;//搜遍了也找不到
//设置I2SxCLK的频率(x=2) 设置PLLI2SN PLLI2SR
RCC->PLLI2SCFGR = ((u32)I2S_PSC_TBL
[1] << 6) | ((u32)I2S_PSC_TBL
[2] << 28);
RCC->CR|=1<<26; //开启I2S时钟
while((RCC->CR&1<<27)==0); //等待I2S时钟开启成功.
tempreg=I2S_PSC_TBL
[3]<<0; //设置I2SDIV
tempreg|=I2S_PSC_TBL
[4]<<8; //设置ODD位
tempreg|=1<<9; //使能MCKOE位,输出MCK
SPI2->I2SPR=tempreg; //设置I2SPR寄存器
return 0;
}
//I2S2 TX DMA配置
//设置为双缓冲模式,并开启DMA传输完成中断
//buf0:M0AR地址.
//buf1:M1AR地址.
//num:每次传输数据量
void I2S2_TX_DMA_Init(u8* buf0,u8 *buf1,u16 num)
{
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_LINKDMA(&I2S_Handle,hdmatx,I2S_TxDMA_Handle);
I2S_TxDMA_Handle.Instance=DMA1_Stream4;
I2S_TxDMA_Handle.Init.Channel=DMA_CHANNEL_0;
I2S_TxDMA_Handle.Init.Direction=DMA_MEMORY_TO_PERIPH;
I2S_TxDMA_Handle.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
I2S_TxDMA_Handle.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_1QUARTERFULL;
I2S_TxDMA_Handle.Init.MemBurst=DMA_MBURST_SINGLE;
I2S_TxDMA_Handle.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;
I2S_TxDMA_Handle.Init.MemInc=DMA_MINC_ENABLE;
I2S_TxDMA_Handle.Init.Mode=DMA_CIRCULAR;
I2S_TxDMA_Handle.Init.PeriphBurst=DMA_PBURST_SINGLE;
I2S_TxDMA_Handle.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;
I2S_TxDMA_Handle.Init.PeriphInc=DMA_PINC_DISABLE;
I2S_TxDMA_Handle.Init.Priority=DMA_PRIORITY_HIGH;
HAL_DMA_DeInit(&I2S_TxDMA_Handle); //先清除以前的设置
HAL_DMA_Init(&I2S_TxDMA_Handle); //初始化DMA
HAL_DMAEx_MultiBufferStart(&I2S_TxDMA_Handle,(u32)buf0,(u32)&SPI2->DR,(u32)buf1,num);//开启双缓冲
__HAL_DMA_DISABLE(&I2S_TxDMA_Handle); //先关闭DMA
__HAL_DMA_ENABLE_IT(&I2S_TxDMA_Handle,DMA_IT_TC); //开启传输完成中断
__HAL_DMA_CLEAR_FLAG(&I2S_TxDMA_Handle,DMA_FLAG_TCIF0_4); //清除DMA传输完成中断标志位
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn,0,0); //DMA中断优先级
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}
//I2S DMA回调函数指针
void (*i2s_tx_callback)(void); //TX回调函数
//DMA1_Stream4中断服务函数
void DMA1_Stream4_IRQHandler(void)
{
/* __HAL_DMA_GET_FLAG(xxx)!=RESET时可以正常工作
__HAL_DMA_GET_FLAG(xxx)==SET时无法正常工作
库文件stm32f4xx_hal_dma.h中说明了FLAG的状态是SET or RESET
The state of FLAG (SET or RESET)
很奇怪!!!
*/
if(__HAL_DMA_GET_FLAG(&I2S_TxDMA_Handle,DMA_FLAG_TCIF0_4)!=RESET)////DMA1_Stream4,传输完成标志
{
__HAL_DMA_CLEAR_FLAG(&I2S_TxDMA_Handle,DMA_FLAG_TCIF0_4); //清除DMA传输完成中断标志位
i2s_tx_callback(); //执行回调函数,读取数据等操作在这里面处理
}
}
//I2S开始播放
void I2S_Play_Start(void)
{
__HAL_DMA_ENABLE(&I2S_TxDMA_Handle);//开启DMA TX传输,开始播放
}
//关闭I2S播放
void I2S_Play_Stop(void)
{
__HAL_DMA_DISABLE(&I2S_TxDMA_Handle);//关闭DMA,结束播放
}
[/mw_shl_code]
加载中...
taizonglai
2楼-- · 2019-07-21 05:44
参考SAI的代码修改。
加载中...
czdspeed
3楼-- · 2019-07-21 06:49
精彩回答 2 元偷偷看……
加载中...
czdspeed
4楼-- · 2019-07-21 08:39
还是有点问题,这个暂时不知道解决的办法,先放到这里吧。待解决了把初始化的步骤贴出来。
加载中...
襟铭心缘
5楼-- · 2019-07-21 10:50
我也遇到同样的问题了,参照SAI的例子和标准库的例子写的,但是在中断里死了
加载中...
czdspeed
6楼-- · 2019-07-21 12:08
襟铭心缘 发表于 2016-9-19 14:20
我也遇到同样的问题了,参照SAI的例子和标准库的例子写的,但是在中断里死了
我最近没搞这个问题,hal库里面的I2s初始化文件搞完了应该没啥问题。不过我的没通,现在单独用sai来配置I2S的。
加载中...
1
2
下一页
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
STM32开发板免费用活动
7 个回答
stm32 处理 DHT11占用太多时间,大家程序是怎么设计的
8 个回答
分享一个STM32单片机做的离线编程器代码
9 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
我的其实配置的没问题,就是在中断函数出的问题,现在已经解决了,可以正常播放音乐。
[mw_shl_code=c,true]#include "bsp_i2s.h"
#include "delay.h"
I2S_HandleTypeDef I2S_Handle;
DMA_HandleTypeDef I2S_TxDMA_Handle;
//开启I2S2的DMA功能,HAL库没有提供此函数
//因此我们需要自己操作寄存器编写一个
void I2S2_DMA_Enable(void)
{
u32 tempreg=0;
tempreg=SPI2->CR2; //先读出以前的设置
tempreg|=SPI_CR2_TXDMAEN; //使能DMA
SPI2->CR2=tempreg; //写入CR1寄存器中
}
void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
GPIO_Initure.Pin=GPIO_PIN_12;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_2;
GPIO_Initure.Alternate=GPIO_AF6_I2S2ext;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_6;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_3;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOD,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_3;
GPIO_Initure.Alternate=GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOI,&GPIO_Initure);
}
//参数I2S_Mode: @ref SPI_I2S_Mode I2S_MODE_SLAVE_TX:从机发送;I2S_MODE_SLAVE_RX:从机接收;I2S_MODE_MASTER_TX:主机发送;I2S_MODE_MASTER_RX:主机接收;
//参数I2S_DataFormat: @ref SPI_I2S_Data_Format :数据长度,I2S_DATAFORMAT_16B,16位标准;I2S_DATAFORMAT_16B_EXTENDED,16位扩展(frame=32bit);I2S_DATAFORMAT_24B,24位;I2S_DATAFORMAT_32B,32位.
void I2S2_Init(u16 I2S_Mode,u16 I2S_DataFormat)
{
I2S_Handle.Instance=SPI2;
__HAL_I2S_DISABLE(&I2S_Handle);
I2S_Handle.Init.Mode=I2S_Mode;
I2S_Handle.Init.Standard=I2S_STANDARD_PHILIPS;
I2S_Handle.Init.DataFormat=I2S_DataFormat;
I2S_Handle.Init.MCLKOutput=I2S_MCLKOUTPUT_ENABLE;
I2S_Handle.Init.AudioFreq=I2S_AUDIOFREQ_DEFAULT;
I2S_Handle.Init.CPOL=I2S_CPOL_LOW;
I2S_Handle.Init.ClockSource=I2S_CLOCK_PLL;
if(HAL_I2S_GetState(&I2S_Handle) == HAL_I2S_STATE_RESET)
{
HAL_I2S_MspInit(&I2S_Handle);
}
HAL_I2S_Init(&I2S_Handle);
__HAL_I2S_ENABLE(&I2S_Handle);
I2S2_DMA_Enable();
}
//采样率计算公式:Fs=I2SxCLK/[256*(2*I2SDIV+ODD)]
//I2SxCLK=(HSE/pllm)*PLLI2SN/PLLI2SR
//一般HSE=25Mhz
//pllm:在Sys_Clock_Set设置的时候确定,一般是8
//PLLI2SN:一般是192~432
//PLLI2SR:2~7
//I2SDIV:2~255
//ODD:0/1
//I2S分频系数表@pllm=25,HSE=25Mhz,即vco输入频率为1Mhz
//表格式:采样率/10,PLLI2SN,PLLI2SR,I2SDIV,ODD
const u16 I2S_PSC_TBL[][5]=
{
{800 ,256,5,12,1}, //8Khz采样率
{1102,429,4,19,0}, //11.025Khz采样率
{1600,213,2,13,0}, //16Khz采样率
{2205,429,4, 9,1}, //22.05Khz采样率
{3200,213,2, 6,1}, //32Khz采样率
{4410,271,2, 6,0}, //44.1Khz采样率
{4800,258,3, 3,1}, //48Khz采样率
{8820,316,2, 3,1}, //88.2Khz采样率
{9600,344,2, 3,1}, //96Khz采样率
{17640,361,2,2,0}, //176.4Khz采样率
{19200,393,2,2,0}, //192Khz采样率
};
//设置IIS的采样率(@MCKEN)
//samplerate:采样率,单位:Hz
//返回值:0,设置成功;1,无法设置.
u8 I2S2_SampleRate_Set(u32 samplerate)
{
u8 i=0;
u32 tempreg=0;
samplerate/=10;//缩小10倍
for(i=0;i<(sizeof(I2S_PSC_TBL)/10);i++)//看看改采样率是否可以支持
{
if(samplerate==I2S_PSC_TBL[0])break;
}
__HAL_RCC_PLLI2S_DISABLE();
if(i==(sizeof(I2S_PSC_TBL)/10))return 1;//搜遍了也找不到
//设置I2SxCLK的频率(x=2) 设置PLLI2SN PLLI2SR
RCC->PLLI2SCFGR = ((u32)I2S_PSC_TBL[1] << 6) | ((u32)I2S_PSC_TBL[2] << 28);
RCC->CR|=1<<26; //开启I2S时钟
while((RCC->CR&1<<27)==0); //等待I2S时钟开启成功.
tempreg=I2S_PSC_TBL[3]<<0; //设置I2SDIV
tempreg|=I2S_PSC_TBL[4]<<8; //设置ODD位
tempreg|=1<<9; //使能MCKOE位,输出MCK
SPI2->I2SPR=tempreg; //设置I2SPR寄存器
return 0;
}
//I2S2 TX DMA配置
//设置为双缓冲模式,并开启DMA传输完成中断
//buf0:M0AR地址.
//buf1:M1AR地址.
//num:每次传输数据量
void I2S2_TX_DMA_Init(u8* buf0,u8 *buf1,u16 num)
{
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_LINKDMA(&I2S_Handle,hdmatx,I2S_TxDMA_Handle);
I2S_TxDMA_Handle.Instance=DMA1_Stream4;
I2S_TxDMA_Handle.Init.Channel=DMA_CHANNEL_0;
I2S_TxDMA_Handle.Init.Direction=DMA_MEMORY_TO_PERIPH;
I2S_TxDMA_Handle.Init.FIFOMode=DMA_FIFOMODE_DISABLE;
I2S_TxDMA_Handle.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_1QUARTERFULL;
I2S_TxDMA_Handle.Init.MemBurst=DMA_MBURST_SINGLE;
I2S_TxDMA_Handle.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;
I2S_TxDMA_Handle.Init.MemInc=DMA_MINC_ENABLE;
I2S_TxDMA_Handle.Init.Mode=DMA_CIRCULAR;
I2S_TxDMA_Handle.Init.PeriphBurst=DMA_PBURST_SINGLE;
I2S_TxDMA_Handle.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;
I2S_TxDMA_Handle.Init.PeriphInc=DMA_PINC_DISABLE;
I2S_TxDMA_Handle.Init.Priority=DMA_PRIORITY_HIGH;
HAL_DMA_DeInit(&I2S_TxDMA_Handle); //先清除以前的设置
HAL_DMA_Init(&I2S_TxDMA_Handle); //初始化DMA
HAL_DMAEx_MultiBufferStart(&I2S_TxDMA_Handle,(u32)buf0,(u32)&SPI2->DR,(u32)buf1,num);//开启双缓冲
__HAL_DMA_DISABLE(&I2S_TxDMA_Handle); //先关闭DMA
__HAL_DMA_ENABLE_IT(&I2S_TxDMA_Handle,DMA_IT_TC); //开启传输完成中断
__HAL_DMA_CLEAR_FLAG(&I2S_TxDMA_Handle,DMA_FLAG_TCIF0_4); //清除DMA传输完成中断标志位
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn,0,0); //DMA中断优先级
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}
//I2S DMA回调函数指针
void (*i2s_tx_callback)(void); //TX回调函数
//DMA1_Stream4中断服务函数
void DMA1_Stream4_IRQHandler(void)
{
/* __HAL_DMA_GET_FLAG(xxx)!=RESET时可以正常工作
__HAL_DMA_GET_FLAG(xxx)==SET时无法正常工作
库文件stm32f4xx_hal_dma.h中说明了FLAG的状态是SET or RESET
The state of FLAG (SET or RESET)
很奇怪!!!
*/
if(__HAL_DMA_GET_FLAG(&I2S_TxDMA_Handle,DMA_FLAG_TCIF0_4)!=RESET)////DMA1_Stream4,传输完成标志
{
__HAL_DMA_CLEAR_FLAG(&I2S_TxDMA_Handle,DMA_FLAG_TCIF0_4); //清除DMA传输完成中断标志位
i2s_tx_callback(); //执行回调函数,读取数据等操作在这里面处理
}
}
//I2S开始播放
void I2S_Play_Start(void)
{
__HAL_DMA_ENABLE(&I2S_TxDMA_Handle);//开启DMA TX传输,开始播放
}
//关闭I2S播放
void I2S_Play_Stop(void)
{
__HAL_DMA_DISABLE(&I2S_TxDMA_Handle);//关闭DMA,结束播放
}
[/mw_shl_code]
我最近没搞这个问题,hal库里面的I2s初始化文件搞完了应该没啥问题。不过我的没通,现在单独用sai来配置I2S的。
一周热门 更多>