本帖最后由 最靓的仔 于 2020-6-13 17:23 编辑
拿到AT板子快两个月了,距离提交项目也没有几天了,我目前的进度是把RT-Thread成功移植到板子上,需要实现功能的裸板程序也已经测试了一个月了,在最后这几天里。我把裸板程序放在RT-Thread这个实时操作系统上。接下来我就说一下我的裸板程序都有什么。
第一个就是bootloader,主要是用于以后升级软件,直接使用对应的上位机,不使用jlink。
第二个就是功能代码,我的功能很简单,就是不断的获取TSIC506温度传感器的信息,然后把这个信息发送给lora模块。
第三个就是低功耗,温度节点对电池的续航要求比较高,所以,当温度节点采集一次温度信息并发送成功后,就立即进入低功耗模式,等待下次的唤醒,唤醒芯片的操作由lora模块来完成。
首先拿到板子之后,先下载官方的例程,跑一个led,看看是否能正常工作。如果能正常工作,那接下来,就开始开发了。
第一个程序,先做一个串口代码
既然是学习,那么所有的代码自己来实现一下是最好的。所以这个串口代码,main函数种的代码,我全部都是自己重新写的,有种重复造轮子的赶脚。。。。
废话不说了,先贴上代码
int main(int argc,const char *argv[])
{
uint8_t ch;
SysClk_PLLEN(PLLCLK_MUL_192MHz);
imu_data_decode_init();
DelayInit();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* serial */
// RCC->APB2EN |= AFIO_ENABLEBIT;
// AFIO->MAP |= AFIO_MAP_USART1_REMAP;
// GPIO_Init(HW_GPIOB, GPIO_PIN_6, GPIO_Mode_AF_PP);
// GPIO_Init(HW_GPIOB, GPIO_PIN_7, GPIO_Mode_IPU);
GPIO_Init(HW_GPIOA, GPIO_PIN_9, GPIO_Mode_AF_PP);
GPIO_Init(HW_GPIOA, GPIO_PIN_10, GPIO_Mode_IPU);
UART_Init(HW_USART1, BAUD_115200);
USART_Cmd(HW_USART1, ENABLE);
GPIO_Init(HW_GPIOA, GPIO_PIN_2, GPIO_Mode_AF_PP);
GPIO_Init(HW_GPIOA, GPIO_PIN_3, GPIO_Mode_IN_FLOATING);
UART_Init(HW_USART2, BAUD_115200);
USART_ITConfig(HW_USART2, UART_INT_RDNE, ENABLE);
USART_Cmd(HW_USART2, ENABLE);
NVIC_Init(USART2_IRQn, 2, 2, ENABLE);
GPIO_Init(HW_GPIOB, GPIO_PIN_8, GPIO_Mode_Out_PP);
GPIO_Init(HW_GPIOB, GPIO_PIN_9, GPIO_Mode_Out_PP);
PBout(8) = 0;
PBout(9) = 0;
printf("hello worle\r\n");
SysTick->LOAD = (float)GetClock_Frequency(pll) / 32000;
systick_setexception(true);
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(1)
{
if(receive_imusol.gyr[2] != 0)
{
SysTick->LOAD = 180000/receive_imusol.gyr[2];
receive_imusol.gyr[2] = 0;
}
}
}
void USART2_IRQHandler(void) //串口2中断服务程序
{
uint8_t ch;
if(UART_GetInter(HW_USART2, UART_INT_RDNE) != RESET) //接收中断
ch = UART_RecviveData(HW_USART2); //读取接收到的数据
frame_rate++;
packet_decode(ch); //解析数据
}
这个代码的功能就是根据读取到的imu芯片数据,输出一个波形,模拟编码器大的波形输出,代码还没有全贴上来,重点是串口的功能实现。从汇编代码中,我们知道,在执行main函数之前,先执行systeminit这个函数,确定时钟频率,不同的板子,不同的芯片,不同的使用环境,对时钟频率的要求也是不一样的,所以,我把systeminit中的代码注释掉,然后我自己来重新实现一下这个功能。然后是imu_data_decode_init函数,这个函数是初始化imu相关的函数,这里它不是重点,跳过。delay_init函数,是初始化延时函数,利用内核systick,来实现延时函数的功能。然后是NVIC_PriorityGroupConfig函数,它是给当前程序进行一个优先级分组。如果不使用这个函数,那么就是默认的分组。
接下来,就是本次代码的重点,串口功能,通过查看电路图和手册。我们确定使用的GPIO引脚,
串口的配置: 1、查看数据手册,查找GPIO引脚定义,找到USART的定义,看看它的收发引脚是用的哪两个GPIO引脚。 2、查看电路图,找到对应的GPIO引脚,看看RX和TX的引脚是否和数据手册一致。防止出错。 3、查看时钟框图,查看对应的串口和GPIO引脚挂载在哪一条总线上。 4、配置对应的GPIO引脚,并使能时钟,RX和TX的模式。 5、配置对应的串口,并使能串口时钟。 6、配置串口的中断触发方式,并使能串口中断方法。 7、使能串口。 8、配置NVIC、串口中断处理函数的抢占和相应优先级,并使能对应的串口号中断。 9、编写串口中断处理函数。 过程中出现的问题: 1、在编译时,提示“对于xxx函数,没有足够信息导出符号表” 解决:先查看函数所在的文件是否添加到工程中,然后查看头文件是否依赖。头文件的名称是否输入正确。头文件的路径是否添加到工程中。 2、第一次编译通过,串口却无法正常工作。 排查:在程序运行时,打开led灯,在串口中断处理函数中添加关灯处理。 用串口调试助手向开发板发送一个字符,led灯无反应。 结论:没有触发中断,没有进入中断处理函数。 解决:查看串口板和开发板的连接是否正确,串口板的RX接开发板的TX,串口板的TX接开发板的RX. 排查代码,先排查GPIO口的配置, RX:接收引脚,PA10,配置:复用推挽输出,speed为50MHz, TX:发送引脚,PA9,配置:浮空输入模式,无speed频率。 使能GPIOA组的时钟,挂载在AP2总线上。 然后是串口的配置:波特率:115200,一个停止位,8位字长,无奇偶校验位,收发工作模式,无硬件流控制。 串口中断触发方式:接受中断使能, 排查串口号的中断使能:查看启动文件,对应的中断处理函数名USART1_IRQHandler。 中断处理函数:在这里需要判断到来的串口中断是不是我们需要的中断,因为我们有可能会使能好几个不同的串口中断。查看我们的接收函数是否正确。 原因:硬件连线错误,位置不对,查看电路图,找到串口的输出引脚,连接之后,成功进入中断。小灯有了变化。 总结:排查代码过程中,我将涉及到算法的地方,直接改成配置相应的寄存器,然后编译,下载。发现还是不行,然后重头开始新一轮的排查,发现硬件连接位置不对。 这个代码,就是利用串口2的中断来接受数据,
|