#申请原创#
@21小跑堂
在初步体验AT32F425开发板的基础上,昨天开始测试芯片的IIC。以例程中communication_int为基础,准备是用IIC口驱动0.96英寸的一块IIC OLED屏,结果搞了一天,也没有成功点亮OLED屏,感觉自己好弱。无奈之下,转而求其次,用GPIO口仿真,直接驱动,以下是代码。 IIC处理部分代码: // 发送开始信号 void IIC_Start(void) { OLED_SCL_SET(); OLED_SDA_SET(); OLED_SDA_CLR(); OLED_SCL_CLR(); } // 发送停止信号 void IIC_Stop(void) { OLED_SDA_CLR(); OLED_SDA_SET(); } // 等到ACK应答 void IIC_Wait_Ack(void) { OLED_SCL_SET(); OLED_SCL_CLR(); } // 发送一字节 void Write_IIC_Byte(uint8_t IIC_Byte) { uint8_ti; uint8_tm,da; da=IIC_Byte; OLED_SCL_CLR(); for(i=0;i<8;i++){ m=da; m=m&0x80; if(m==0x80){ OLED_SDA_SET(); }else { OLED_SDA_CLR(); } da=da<<1; OLED_SCL_SET(); OLED_SCL_CLR(); } } // 写一字节指令 void Write_IIC_Command(uint8_t IIC_Command){ IIC_Start(); Write_IIC_Byte(IIC_OLED_ADDR); //Slave address,SA0=0 IIC_Wait_Ack(); Write_IIC_Byte(0x00); //write command IIC_Wait_Ack(); Write_IIC_Byte(IIC_Command); IIC_Wait_Ack(); IIC_Stop(); } // 写一字节数据 void Write_IIC_Data(uint8_t IIC_Data) { IIC_Start(); Write_IIC_Byte(IIC_OLED_ADDR); //D/C#=0; R/W#=0 IIC_Wait_Ack(); Write_IIC_Byte(0x40); //write data IIC_Wait_Ack(); Write_IIC_Byte(IIC_Data); IIC_Wait_Ack(); IIC_Stop(); } 头文件内容: //定义IIC从设备地址 #define IIC_OLED_ADDR 0x78 //--------------IIC总线引脚定义----------------------- #define OLED_GPIO_PORT GPIOB #define OLED_PERIPH_CLOCK CRM_GPIOB_PERIPH_CLOCK #define OLED_SCL GPIO_PINS_15 //OLED屏IIC时钟信号 #define OLED_SDA GPIO_PINS_14 //OLED屏IIC数据信号 //--------------IIC端口操作定义--------------------- #define OLED_SDA_SET() gpio_bits_set(OLED_GPIO_PORT,OLED_SDA);delay_us(1); #define OLED_SDA_CLR() gpio_bits_reset(OLED_GPIO_PORT,OLED_SDA);delay_us(1); #define OLED_SCL_SET() gpio_bits_set(OLED_GPIO_PORT,OLED_SCL);delay_us(1); #define OLED_SCL_CLR() gpio_bits_reset(OLED_GPIO_PORT,OLED_SCL);delay_us(1); //IIC操作函数 void IIC_Start(void); void IIC_Stop(void); void IIC_Wait_Ack(void); void Write_IIC_Byte(u8 IIC_Byte); void Write_IIC_Command(u8 IIC_Command); void Write_IIC_Data(u8 IIC_Data); 这里要说明的是,SCL和SDA关联到的GPIO口,一定要仔细确认,避免使用被系统默认转做他用的GPIO口;另外,IIC端口操作定义中后面追加了delay_us(1);事实上,在没有追加这个延时处理的时候,程序下载后,代码明明被执行了,但OLED没有任何显示内容。但这些处理代码,在另外一块STM32芯片的板子上是完全没有问题,可以显示的。想了想,是不是由于IIC总线上的脉冲周期太短,导致无法正常通讯。于是追加了延时处理。结果编译、下载后显示就正常了。以下是运行图:
使用杜邦线连接开发板和OLED。屏幕上显示的是菜单,通过开发板上的“USER”按钮(占用PA0资源),利用中断方式,每触发一次按钮,中断一次,改变菜单的选中状态。为了在工程中引入中断处理,需要在工程中添加中断处理用的C文件at32f425_int.c,这个文件替换掉原来的同名文件;在firmware组中添加at32f425_exint.c和at32f425_scfg.c两个C文件。 在主程序文件中加入外部中断配置处理和外部中断处理函数。 // 外部中断配置 void exint_line0_config(void) { exint_init_type exint_init_struct; crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); // PA0作为中断源 scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE0); exint_default_para_init(&exint_init_struct); exint_init_struct.line_enable = TRUE; exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT; exint_init_struct.line_select = EXINT_LINE_0; exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE; exint_init(&exint_init_struct); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); nvic_irq_enable(EXINT1_0_IRQn, 1, 0); } // 外部中断处理函数 void EXINT1_0_IRQHandler(void) { if(exint_flag_get(EXINT_LINE_0) != RESET) { delay_ms(20); if(exint_flag_get(EXINT_LINE_0) != RESET) { exint_flag_clear(EXINT_LINE_0); menu_idx=(menu_idx+1)%3; } } } 为了防止干扰,在中断处理函数中追加了延时处理delay_ms(20)。 在主程序中加入以下处理代码: // 初始化系统时钟 system_clock_config(); /* config nvic priority group */ nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); // 开发板初始化 at32_board_init(); // OLED初始化 OLED_Init(); OLED_Clear(0); //清屏(全黑) // 设置PA0为外部中断模式 exint_line0_config(); 为了能在程序中使用printf函数向串口输出信息,需要在开发板初始化函数at32_board_init中追加串口的初始化处理uart_print_init, void at32_board_init() { /*initialize delay function */ delay_init(); /*configure led in at_start_board */ at32_led_init(LED2); at32_led_init(LED3); at32_led_init(LED4); at32_led_off(LED2); at32_led_off(LED3); at32_led_off(LED4); /*configure button in at_start board */ at32_button_init(); // 串口初始化,115200波特率 uart_print_init(115200); } at32_board_init是at32f425_board.c中的一个函数。应该说,这个开发板提供的一些处理已经包含在at32f425_board.c文件中,使用起来非常方便。开发板中用到的LED2、3、4和用户按钮的初始化处理,也已经被包含了。uart_print_init这个函数也是一起提供的,直接拿来用就行。这些处理开发者直接使用,完全不需要额外添加代码,非常用心地为开发者着想。 工程中用到的相关文件,用截图表示,不再一一列出了。
显示部分已经完成,接下来,准备接入PS2键盘、无线通讯模块。预想的是以开发板为主控,通过键盘设置必要的参数,动态控制外围设备,完成无人状态下的日常处理。当然有时间的话,继续调IIC,考虑使用例程中利用IIC读写EEPROM的那个。
|