主芯片GD32E230C8T6 /4段8位数码管/GN1650驱动芯片(IIC通讯)/USART/485通讯芯片
说明使用PA9、 PA10的USART0时要选择AF1;
初始化USART0 时才有了这两句;
与GD32E103不同的是E230没有gpio_init这个库函数,所以参考例程是有帮助的;
/* connect port to USARTx_Tx */
gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9);
/* connect port to USARTx_Rx */
gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10);
可以看到E230有64K的主flash,这里我选了0x0800 FC00,操作最后一页;
main.h
//IIC所有操作函数
void i2c_init(void); //初始化IIC的IO口
static void IIC_Start1(void);
static void IIC_Stop1(void);
uint8_t IIC_Rev_Byte(void); //对IIC数据进行读出
void IIC_Wrt_Byte(uint8_t data); //IIC发送一个字节
void IIC_ACK(void); //IIC发送信号
void IIC_NAck(void); //IIC不发送ACK信号
void SDA_Rx(void); //主机recv from 从机
/************** GN1650 **************/
void GN1650_display(void); //数码管显示
void GN1650_display_D(void); //数码管无显示
void GN1650_Wrt_RAM(uint8_t Address, uint8_t Data); //对IIC数据进行写入
uint8_t GetKey(void); //按键扫描
/************** usart ************/
void usart0_init();
/************** flash ************/
uint8_t FMC_FLASH_Write( u32 data );
uint8_t FMC_FLASH_Read(u32 *data );
main.c
#define READ_SDA gpio_input_bit_get(GPIOB,GPIO_PIN_7)
#define LEDDOT 0x80
#define MAXNUM 10
#define TIMEPRESS 350 //key press times
#define DIG1 17
#define DIG2 25
#define DIG3 21
#define DIG4 29
#define ADDRMAX 512
uint8_t i;
uint16_t value=0;
void myGPIO_init(void)
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOA);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ,GPIO_PIN_0);//PB6_42 I2C0_SCL GPIO_OTYPE_PP推挽输出
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0);
}
void keycheck(void)
{
uint16_t KeyNum;
uint16_t LastKeyNum = 0;
static uint8_t Keyleased=1,fastCnt=0;
static uint16_t keydowntime = 0;
KeyNum = GetKey();
switch(KeyNum)
{
case DIG2:
if(keydowntime++ >= TIMEPRESS )//long press ++
{
keydowntime=TIMEPRESS;
if(++fastCnt>=10)//add press times 分频
{
fastCnt=0;
value++;
if(value > ADDRMAX) value = 1; //512 to 1
}
}
else if(Keyleased && keydowntime < TIMEPRESS )//short press ++
{
value++;
Keyleased = 0;
if(value > ADDRMAX) value = 1; //512 to 1
}
break;
case DIG3:
if( keydowntime++ >= TIMEPRESS)//long press --
{
keydowntime=TIMEPRESS;
if(++fastCnt>=10)//add press times 分频
{
fastCnt=0;
value--;
if(value == 0) value = ADDRMAX; //0 to 512
}
}
else if(Keyleased && keydowntime++ < TIMEPRESS )//short press --
{
value--;
Keyleased=0; //keydown locked
if(value == 0) value = ADDRMAX; //0 to 512
}
break;
case DIG4:
if(Keyleased)
{
FMC_FLASH_Write(value);
printf("****value=%d****\r\n",value);
Keyleased = 0;
}
break;
default:
Keyleased=1;//keydown loosed
fastCnt=0;
keydowntime = 0;
//lontimeflag = 1;
break;
}
}
//主函数处理
int main(void)
{
uint8_t flag = 0;
systick_config();
delay_ms(10);
usart0_init();
//myGPIO_init();
delay_ms(10);
i2c_init();
FMC_FLASH_Read((u32 *)&value);//read flash
while(1)
{
flag =!flag;
gpio_bit_write(GPIOA,GPIO_PIN_0,flag);
delay_ms(1);
keycheck();
GN1650_display();
//do work1
//do work2
}
}
/********** 数码管显示 **********/
void GN1650_display(void)
{
GN1650_Wrt_RAM(0x68,LEDENCODE[value/1000%10]);//high //0x48 系统指令 0x41//4级亮度 8段显示 显示开
GN1650_Wrt_RAM(0x6A,LEDENCODE[value/100%10] );// ;
GN1650_Wrt_RAM(0x6C,LEDENCODE[value/10%10]);
GN1650_Wrt_RAM(0x6E,LEDENCODE[value%10] ); //low
GN1650_Wrt_RAM(0x48,0x01);
}
/********** 数码管无显示 **********/
void GN1650_display_D(void)
{
GN1650_Wrt_RAM(0x48,0x00);
}
/********** IIC初始化 *********/
void i2c_init(void)
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* enable I2C0 clock */
rcu_periph_clock_enable(RCU_I2C0);
/* connect PB6 to I2C0_SCL */
gpio_af_set(GPIOB,GPIO_AF_1,GPIO_PIN_6);
/* connect PB7 to I2C0_SDA */
gpio_af_set(GPIOB,GPIO_AF_1,GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_6);//PB6_42 I2C0_SCL
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_6);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_7);//PB7_43 I2C0_SDA
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
/* configure I2C0 clock */
//i2c_clock_config(I2C0,60000,I2C_DTCY_2);
/* enable I2C0 */
i2c_enable(I2C0);
/* enable acknowledge */
i2c_ack_config(I2C0,I2C_I2CMODE_ENABLE);
/* 空闲状态 */
gpio_bit_write(GPIOB,GPIO_PIN_6,1);
gpio_bit_write(GPIOB,GPIO_PIN_7,1);
GN1650_Wrt_RAM(0x48,0x00);//关闭显示
}
void SDA_Rx(void) //主机recv from 从机
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
}
void SDA_Tx(void)
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ,GPIO_PIN_7);//PB7_43 I2C0_SDA
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_7);
}
void IIC_SCL(uint8_t n)
{
gpio_bit_write(GPIOB,GPIO_PIN_6,n);
}
void IIC_SDA(uint8_t n)
{
gpio_bit_write(GPIOB,GPIO_PIN_7,n);
}
static void IIC_Delay(void)
{
__IO uint16_t cnt=1;
while(cnt--);
}
/*********************模拟IIC通信****************/
/*
*函数功能:IIC起始
*提 示:
*输入参数:无
*输出参数:无
*返回值 :无
*/
static void IIC_Start1(void)
{
SDA_Tx();
//2、SCL 1
IIC_SCL(1);
//3、SDA 1
IIC_SDA(1);
//延时5us
IIC_Delay();
//4、SCL 0
IIC_SDA(0);
//延时5us
IIC_Delay();
//5、SDA 0
IIC_SCL(0);
//延时5us
IIC_Delay();
}
/*
*函数功能:IIC结束
*提 示:
*输入参数:无
*输出参数:无
*返回值 :无
*/
static void IIC_Stop1(void)
{
//2、SCL 1
IIC_SCL(1);
//3、SDA 0
IIC_SDA(0);
//延时5us
IIC_Delay();
//4、SDA 1
IIC_SDA(1);
//延时5us
IIC_Delay();
}
/*
*函数功能:IIC应答
*提 示:
*输入参数:无
*输出参数:无
*返回值 :无
*/
void IIC_ACK(void)
{
SDA_Rx();
IIC_SCL(0);
IIC_Delay();
IIC_SDA(0);
IIC_Delay();
IIC_SCL(1);
IIC_Delay();
IIC_SCL(0);
IIC_Delay();
SDA_Tx();
IIC_SDA(0);
IIC_Delay();
}
/****************模拟IIC通信**************/
/* 描述:一个字节数据发送函数
* 参数: 无
* 返回值:无 */
void IIC_Wrt_Byte(uint8_t data)
{
int i;
IIC_SCL(0); //拉低时钟开始数据传输
for(i = 0;i < 8;i++)
{
IIC_SDA((data & 0x80)>0 ); //check bit7
data <<= 1;
IIC_Delay(); //这三个延时都是必须的
IIC_SCL(1);
IIC_Delay();
IIC_SCL(0);
IIC_Delay();
}
}
/* 描述:一个字节数据接收函数
* 参数: 无
* 返回值:接收到的字节数据 */
uint8_t IIC_Rev_Byte(void)
{
uint8_t dat=0;
uint8_t i;
SDA_Rx(); /* 设置数据线为输入方式 */
IIC_Delay();
for(i = 0;i < 8;i++)
{
IIC_SCL(0); /* 设置时钟线为低,准备接收数据位 */
IIC_Delay();
IIC_SCL(1); /* 设置时钟线为高使数据线上数据有效 */
if(READ_SDA) dat|=0x80; //同ret++; /* 读数据位,接收的数据位放入ret中 */
dat>>=1;
IIC_Delay();
}
IIC_SCL(0);
return dat;
}
// write to RAM
void GN1650_Wrt_RAM(uint8_t Address, uint8_t Data)
{
IIC_Start1();
IIC_Wrt_Byte(Address);
IIC_ACK();
IIC_Wrt_Byte(Data);
IIC_ACK();
IIC_Stop1();
}
/********** get 4 按键 ID **********/
uint8_t GetKey(void)
{
uint8_t key=0;
IIC_Start1();
IIC_Wrt_Byte(0x49);
IIC_ACK();
key= IIC_Rev_Byte();
IIC_ACK();
IIC_Stop1();
return key;
}
#define ADDRSTART 0x0800FC00
/****************** flash write **************/
/*!
\brief FLASH写
@Address 操作地址
@Size 数据长度
*/
uint8_t FMC_FLASH_Write(u32 data)
{
fmc_state_enum FLASHStatus;
uint16_t i;
uint32_t Address = ADDRSTART;
/* 解锁 */
fmc_unlock();
/* step1: erase pages */
fmc_page_erase(Address);
/* step2: 操作FMC前先清空STAT 状态寄存器,非常必要*/
fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR );
fmc_word_program(Address, data);
fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGAERR | FMC_FLAG_PGERR );
/* 上锁 */
fmc_lock();
return 0;
}
/****************** flash read **************/
/*!
\brief FLASH读
@Address 操作地址
@data 数据指针
*/
uint8_t FMC_FLASH_Read(u32 *data)
{
uint32_t Address = ADDRSTART;
*data = *( __IO uint32_t* ) Address;
return 0;
}
/****************** usart0 print **************/
void usart0_init() // 初始化串口0
{
/* enable COM GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA); // 使能GPIOA时钟
rcu_periph_clock_enable(RCU_GPIOB); // 使能GPIOB时钟
rcu_usart_clock_config(CK_APB2);
rcu_periph_clock_enable(RCU_USART0); // 使能串口0时钟
/* connect port to USARTx_Tx */
gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9);
/* connect port to USARTx_Rx */
gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10);
/* configure USART Tx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
/* configure USART Rx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/***** 485 TX enable ****/ //pin13--PB13
gpio_mode_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_13); //GPIO_OSPEED_2MHZ
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_13);
gpio_bit_set(GPIOB,GPIO_PIN_13); //0-Rx
// 步骤1-7:
usart_deinit(USART0); //reset USART0
usart_word_length_set(USART0,USART_WL_8BIT); ///2、配置USART字长
usart_stop_bit_set(USART0,USART_STB_1BIT); ///3、配置USART停止位
usart_parity_config(USART0, USART_PM_NONE);//4、奇偶校验位
usart_baudrate_set(USART0,115200); ///5、配置USART波特率
usart_transmit_config(USART0,USART_TRANSMIT_ENABLE); // 6、USART发送配置
usart_receive_config(USART0,USART_RECEIVE_ENABLE);
usart_enable(USART0);//使能串口
// 在nvic中配置中断向量和中断优先级
nvic_irq_enable(USART0_IRQn,1); //使能NVIC的中断
// 使能USART子中断
usart_interrupt_enable(USART0,USART_INT_RBNE);
}
// 中断处理函数
void USART0_IRQHandler(void)
{
// 串口2外部给串口2发送了数据,就会进入下面这个中断,然后把数据读取到data里面
if( RESET != usart_interrupt_flag_get(USART0,USART_INT_FLAG_RBNE) )// 发生中断,则返回RESET
{
usart_data_receive(USART0); // 读取串口接收到的数据
}
usart_interrupt_flag_clear(USART0,USART_INT_FLAG_ERR_FERR);
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
return ch;
}
************ 版权所有,转载请注明出处 ************
共同监督,一起努力!!!