RISC-V内核中科蓝讯BT8922开发
Posted aron566
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RISC-V内核中科蓝讯BT8922开发相关的知识,希望对你有一定的参考价值。
RISC-V内核中科蓝讯BT8922开发
BT8922
GPIO配置
官方说明部分
GPIOAFEN //0:当作通用GPIO使用 //1:当作其它功能性IO,如串口/SPI..
GPIOADE //数字IO使能: 0为模拟IO, 1 为数字IO, //如作为AUX/MIC输入的IO口就需要设置成模拟IO, 减少数字IO对AUX的干扰.
GPIOADIR //控制IO的方向: 0为输出, 1为输入.
GPIOA //IO方向为输入时,读此寄存器的值即得到引脚的高低状态 //IO为输出时, 设置此寄存器的高低即设置对应引脚的高低输出.
GPIOADRV //0 输出驱动为8mA //1 输出驱动为32 mA //IO方向为输出时有效
//以下寄存器控制上拉或下拉, 注意只有当IO设置为输入时, 上下拉才有效. //IO方向为输出时上下拉自动无效
GPIOAPU //10K上拉使能
GPIOAPD //10K下拉使能
GPIOAPU200K //200K上拉使能
GPIOAPD200K //200K下拉使能
GPIOAPU300 //300欧上拉使能
GPIOAPD300 //300欧下拉使能
//作为输出时,输出电平的高低也可以通过设置GPIOASET/GPIOACLR来快速实现,注意GPIOASET/GPIOACLR只对写1的位有效.
GPIOASET = BIT(0); //PA0输出高, 等效于 GPIOA |= BIT(0);其它位状态不变.
GPIOACLR = BIT(0); //PA0输出低, 等效于GPIOA &= ~BIT(0);其它位状态不变.
常见输入输出使用示例: 1. PA0输出高低(点LED灯)示例:
int main(void)
//示例开始
GPIOAFEN &= ~BIT(0); //PA0作为GPIO使用
GPIOADE |= BIT(0); //PA0设置为数字IO
GPIOADIR &= ~BIT(0); //PA0方向设置为输出
WDT_DIS(); //测试程序关看门狗,防止看门狗复位
while(1)
GPIOA |= BIT(0); //PA0输出高, 等效于GPIOASET = BIT(0);
delay_ms(100);
GPIOA &= ~BIT(0); //PA0输出低, 等效于GPIOACLR = BIT(0);
delay_ms(100);
配置得到PA0引脚状态(作用输入)示例:
int main(void)
//示例开始
GPIOAFEN &= ~BIT(0); //PA0作为GPIO使用
GPIOADE |= BIT(0); //PA0设置为数字IO
GPIOADIR |= BIT(0); //PA0方向设置为输入
GPIOAPU |= BIT(0); //作为输入,为了有稳定的输入状态(1或0),在外部没上拉或下拉时,需要根据实际情况开内部上拉或下拉
WDT_DIS(); //测试程序关看门狗,防止看门狗复位
while(1)
delay_ms(100);
printf("GPIOA0 = 0x%X\\n",GPIOA & BIT(0)); //打印读到的PA0状态
关于 GPIOASET/ GPIOACLR: 只对写入为1的位有效, 写入为0的位则不影响它以前的状态的. 如PA0输出高低
GPIOASET = BIT(0); //PA0输出高, 等效于 GPIOA |= BIT(0);
GPIOACLR = BIT(0); //PA0输出低, 等效于GPIOA &= ~BIT(0);
GPIO输出控制优化加速
此两个寄存器, 主要是优化IO输出高低电平而设置. 如设置PA0为高, 为了不影响GPIOA上的其它IO的操作, 以前程序一般这样写GPIOA |= BIT(0); 这里实际上有三个步骤:
1) 先读出GPIOA
2) 再把GPIOA | BIT(0)
3) 把或后的结果再写回GPIOA
而使用GPIOASET效优化后, 直接一步GPIOASET = BIT(0);
即达到 上面三步才能达到的效.
GPIOADE &= ~BIT(7);//模拟:0 or 数字:1
/* 功能选择 */
GPIOAFEN &= ~BIT(7);//普通IO:0 or 复用IO:1
/* 上下拉控制 */
GPIOAPU &= ~BIT(7);//10Kohm 上拉使能(输入有效) 0不用 1使能
GPIOAPU200K &= ~BIT(7);//200Kohm 上拉使能(输入有效) 0不用 1使能
GPIOAPU300 &= ~BIT(7);//300ohm 上拉使能(输入有效) 0不用 1使能
GPIOAPD &= ~BIT(7);//10Kohm 下拉使能(输入有效) 0不用 1使能
GPIOAPD300 &= ~BIT(7);//300ohm 下拉使能(输入有效) 0不用 1使能
GPIOAPD200K &= ~BIT(7);//200Kohm 下拉使能(输入有效) 0不用 1使能
/* 输入输出控制 */
GPIOADIR |= BIT(7);//方向选择 0输出 1输入
/* 驱动能力控制 */
GPIOADRV |= BIT(7);//驱动电流 写0 8 or 写1 32mA
/* 端口功能映射控制 */
FUNCMCON0 =
【31:28】UART1 RX mapping
0000: no affect
0001: map to G1
0010: map to G2
0011: map to TX pin by UT1TXMAP select
1111: Clear these bits
【27:24】UART1 TX mapping
0000: no affect
0001: map to G1
0010: map to G2
1111: Clear these bits
【15:12】UART0 RX mapping
0000: no affect
0001: map to G1
0010: map to G2
0011: map to G3
0100: map to G4
0101: map to G5
0110: map to G6
0111: map to TX pin by UT0TXMAP select
1111: Clear these bits
【11:8】UART0 TX mapping
0000: no affect
0001: map to G1
0010: map to G2
0011: map to G3
0100: map to G4
0101: map to G5
0110: map to G6
0111: map to G7
1111: Clear these bits
【7:4】SPI0 mapping
0000: no affect
0001: map to G1
0010: map to G2
0011: map to G3
1111: Clear these bits
【3:0】SD0 mapping
0000: no affect
0001: map to G1
0010: map to G2
0011: map to G3
0100: map to G4
0101: map to G5
0110: map to G6
1111: Clear these bits
FUNCMCON1 =
【11:8】UART2 RX mapping
0000: no affect
0001: map to G1
0010: map to G2
0011: map to TX pin by UT2TXMAP select
1111: Clear these bits
【7:4】UART2 TX mapping
0000: no affect
0001: map to G1
0010: map to G2
1111: Clear these bits
FUNCMCON2 = /* 设置定时器 */
FUNCMCON2 = /* 设置MPDM interface mapping 和 PDM interface mapping */
对于G1这种IO组合名称定义,查阅config_define.h
,以及在Datasheet文件中找到相关定义
配置一个端口为串口
GPIOADE |= BIT(7);//数字
GPIOAPU |= BIT(7);//上拉10Kohm
GPIOADIR |= BIT(7);//方向选择1输入
GPIOAFEN |= BIT(7);//功能复用IO
GPIOADRV |= BIT(7);//驱动电流32mA
#define URX0MAP_TX (7<<12) //0111 0000 0000 0000
#define UTX0MAP_PA7 (1 << 8)//0000 0001 0000 0000
FUNCMCON0 = URX0MAP_TX | UTX0MAP_PA7;//RX0 Map To TX0, TX0 Map to G1
通过对照手册,设定UART1的相关寄存器设置,在config_define.h中
PS:数据手册中对UART1的RX脚没有G2相关描述,不过控制寄存器中存在G2组,这是datasheet无法与用户手册对应的地方!!!
/*****************************************************************************
* Module : uart1 Mapping选择列表 用户手册与数据手册冲突,以数据手册为准
*****************************************************************************/
#define UTX1MAP_PA7 (1 << 24) //G1 uart1 tx: PA7
#define UTX1MAP_VUSB (3 << 24) //G3 uart1 tx: VUSB
#define URX1MAP_PA6 (1 << 28) //G1 uart1 rx: PA6
/*****************************************************************************
* Module : uart2 Mapping选择列表 以数据手册为准
*****************************************************************************/
#define UTX2MAP_PB2 (2 << 4) //G2 uart2 tx: PB2
#define UTX2MAP_VUSB (3 << 4) //G3 uart2 tx: VUSB
#define UTX2MAP_CLR (0xF << 4) //清除映射
#define URX2MAP_PB1 (2 << 8) //G2 uart2 rx: PB1
#define URX2MAP_CLR (0xF << 8) //清除映射
配置为普通GPIO
/*****************************************************************************
* Module : GPIO list
*****************************************************************************/
#define IO_NONE 0
#define IO_PA0 1
#define IO_PA1 2
#define IO_PA2 3
#define IO_PA3 4
#define IO_PA4 5
#define IO_PA5 6
#define IO_PA6 7
#define IO_PA7 8
#define IO_PB0 9
#define IO_PB1 10
#define IO_PB2 11
#define IO_PB3 12
#define IO_PB4 13
#define IO_PE0 14
#define IO_PE1 15
#define IO_PE2 16
#define IO_PE3 17
#define IO_PE4 18
#define IO_PE5 19
#define IO_PE6 20
#define IO_PE7 21
#define IO_PF0 22
#define IO_PF1 23
#define IO_PF2 24
#define IO_PF3 25
#define IO_PB5 26
#define IO_MAX_NUM 26
#define IO_MUX_SDCLK 27
#define IO_MUX_SDCMD 28
#define IO_MUX_PWRKEY 29
#define IO_MUX_MICL 30
typedef struct
psfr_t sfr; //GPIO SFR ADDR
u8 num;
u8 type; //type = 1,高压IO,没有300R的强上下拉电阻。 type = 0, 普通IO, 有内部300R上下拉电阻。
gpio_t;
/* 配置IO,io_num就是上表中数字 */
gpio_cfg_init(gpio_t *g, u8 io_num);
简化普通GPIO配置
/* GPIO基础配置 */
#define GET_GPIO_DE_REG(port) GPIO##port##DE
#define GET_GPIO_FEN_REG(port) GPIO##port##FEN
#define GET_GPIO_DIR_REG(port) GPIO##port##DIR
#define GET_GPIO_DRV_REG(port) GPIO##port##DRV
#define GET_GPIO_DATA_REG(port) GPIO##port
#define GET_GPIO_SET_REG(port) GPIO##port##SET
#define GET_GPIO_CLR_REG(port) GPIO##port##CLR
/* 上拉控制 */
#define GET_GPIO_10K_PUP_REG_ADDR(port) GPIO##port##PU
#define GET_GPIO_200K_PUP_REG_ADDR(port) GPIO##port##PU200K
#define GET_GPIO_300_PUP_REG_ADDR(port) GPIO##port##PU300
#define GET_GPIO_10K_PUP_REG_ADDR(port) GPIO##port##PU
/* 下拉控制 */
#define GET_GPIO_10K_PD_REG_ADDR(port) GPIO##port##PD
#define GET_GPIO_200K_PD_REG_ADDR(port) GPIO##port##PD200K
#define GET_GPIO_300_PD_REG_ADDR(port) GPIO##port##PD300
#define GET_GPIO_10K_PD_REG_ADDR(port) GPIO##port##PD
/**
* @brief 配置32mA电流输出端口
* @param port 端口
* @param pin 引脚号PAx
*
*/
#define GPIO_CONFIG_OUTPUT_MODE(port, pin) \\
do \\
GET_GPIO_DE_REG(port) |= BIT(pin); \\
GET_GPIO_FEN_REG(port) &= ~BIT(pin); \\
GET_GPIO_DIR_REG(port) &= ~BIT(pin); \\
GET_GPIO_DRV_REG(port) |= BIT(pin); \\
GET_GPIO_CLR_REG(port) = BIT(pin); \\
while(0)
/**
* @brief 配置8mA低电流驱动输出
* @param port 端口
* @param pin 引脚号PAx
*
*/
#define GPIO_CONFIG_SAMALL_OUTPUT_MODE(port, pin) \\
do \\
GET_GPIO_DE_REG(port) |= BIT(pin); \\
GET_GPIO_FEN_REG(port) &= ~BIT(pin); \\
GET_GPIO_DIR_REG(port) &= ~BIT(pin); \\
GET_GPIO_DRV_REG(port) &= ~BIT(pin); \\
GET_GPIO_CLR_REG(port) = BIT(pin); \\
while(0)
/**
* @brief 配置引脚输入模式,默认10K上拉
* @param port 端口
* @param pin 引脚号PAx
*
*/
#define GPIO_CONFIG_INPUT_MODE(port, pin) \\
do \\
GET_GPIO_DE_REG(port) |= BIT(pin); \\
GET_GPIO_FEN_REG(port) &= ~BIT(pin); \\
GET_GPIO_DIR_REG(port) |= BIT(pin); \\
GET_GPIO_DRV_REG(port) |= BIT(pin); \\
GET_GPIO_10K_PUP_REG_ADDR(port) |= BIT(pin); \\
while(0)
/**
* @brief 设置引脚高电平
* @param port 端口
* @param pin 引脚号PAx
*
*/
#define SET_GPIO_TO_HIGH(port, pin) \\
do \\
GET_GPIO_SET_REG(port) = BIT(pin); \\
while(0)
/**
* @brief 设置引脚低电平
* @param port 端口
* @param pin 引脚号PAx
*
*/
#define SET_GPIO_TO_LOW(port, pin) \\
do \\
GET_GPIO_CLR_REG(port) = BIT(pin); \\
while(0)
/**
* @brief 获取引脚电平
* @param port 端口
* @param pin 引脚号PAx
*
*/
#define GET_GPIO_DATA(port, pin) \\
(GET_GPIO_DATA_REG(port) & BIT(pin))
static void Test_GPIO_Init(void)
// /* 使能数字GPIO PE5 */
// GPIOEDE |= BIT(5);
// /* 普通IO口功能 */
// GPIOEFEN &= ~BIT(5);
// /* 设置为输出 */
// GPIOEDIR &= ~BIT(5);
// /* 设置高电流驱动 */
// GPIOEDRV |= BIT(5);
// /* 设置为低电平 */
// GPIOE &= ~BIT(5);
GPIO_CONFIG_OUTPUT_MODE(E, 5);
static void Test_GPIO_Out(uint8_t GPIO_State)
if(GPIO_State)
// GPIOE |= BIT(5);
SET_GPIO_TO_HIGH(E, 5);
else
// GPIOE &= ~BIT(5);
SET_GPIO_TO_LOW(E, 5);
简化后的GPIO配置自定义LED
蓝讯有配置LED闪烁方式的工具(download),默认高电平点亮,内部配置IO看不到,所以在自己的电路中如果灯是低电平点亮,就无法使用工具进行配置LED,需要我们做下修改(配置IO、设置高低电平的接口由我们自己代码定义,闪烁周期方式由配置工具定义)
并不推荐这么做,功能由sdk实现的就尽量不动里面的代码,对后续升级sdk方便一点
1、在port_led.c
文件中增加如下接口
我们在bsp_led.c中实现这些接口:注意代码放置在.com区域
#必看-中科蓝讯开发环境搭建-基础开发环境搭建说明
Linux 内核加速支持 Rust 开发;中科院计划每半年升级一次 RISC-V 芯片;Python 3.10.1 发布 | 开源日报
RT-Thread X RISC-V创新应用大赛,500套开发板免费送!