K64 计算 UART波特率
bootloader UART 流程分析
1 scuart_full_init 初始化 UART,初始化过程包含注册回调函数,当接收到数据时RX 接收引脚发生中断,调用回调函数 instance_transition_callback。
2 进入函数 scuart_poll_for_activity,主要是对 回调函数 instance_transition_callback 二次处理. 最终得到UART 波特率,使用得到的波特率重新初始化UART,
bootloader_initget_active_peripheralscuart_full_initautobaud_init(self->instance);void autobaud_init(uint32_t instance)
{s_transitionCount = 0;s_firstByteTotalTicks = 0;s_secondByteTotalTicks = 0;s_lastToggleTicks = 0;s_instanceMeasured = 0;s_ticksBetweenFailure = microseconds_convert_to_ticks(kMaximumTimeBetweenFallingEdges);enable_autobaud_pin_irq(instance, instance_transition_callback);
}//RX引脚将下降沿中断回调函数,每产生一个下降沿中断 会计算每一个下降沿时刻,并将相邻的两个下降沿事件
//差值保存在 s_ticksFallingEdges 数组里面;
void instance_transition_callback(uint32_t instance)
{uint64_t ticks = microseconds_get_ticks();s_transitionCount++;uint64_t delta = ticks - s_lastToggleTicks;// The last toggle was longer than we allow so treat this as the first oneif (delta > s_ticksBetweenFailure){s_transitionCount = 1;}switch (s_transitionCount){case 1:// This is our first falling edge, store the initial ticks temporarily in firstByteTicks// and save the instance that we are measurings_ticksAtFirstFallingEdge = ticks;s_firstByteTotalTicks = ticks;s_instanceMeasured = instance;break;case kFirstByteRequiredFallingEdges:// We reached the end of our measurable first byte, subtract the current ticks from the initial// first byte tickss_firstByteTotalTicks = ticks - s_firstByteTotalTicks;break;case (kFirstByteRequiredFallingEdges + 1):// We hit our first falling edge of the second byte, store the initial ticks temporarily in secondByteTickss_secondByteTotalTicks = ticks;break;case (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges):// We reached the end of our measurable second byte, subtract the current ticks from the initial// second byte tickss_secondByteTotalTicks = ticks - s_secondByteTotalTicks;disable_autobaud_pin_irq(instance);break;}s_ticksFallingEdges[s_transitionCount - 1] = ticks - s_ticksAtFirstFallingEdge;//[7-1] = 15127s_lastToggleTicks = ticks;
}//注册UART RX 引脚下降沿中断函数
//Blhost 发送两个字节 0x5a 和 0xa5,RX引脚将产生7个下降沿中断。
void enable_autobaud_pin_irq(uint32_t instance, pin_irq_callback_t func)
{switch (instance){case 0:// Only look for a falling edge for our interruptsPORT_SetPinInterruptConfig(UART0_RX_PORT_BASE, UART0_RX_GPIO_PIN_NUM, kPORT_InterruptFallingEdge);NVIC_SetPriority(UART0_RX_GPIO_IRQn, PORT_IRQC_INTERRUPT_ENABLED_PRIORITY);NVIC_EnableIRQ(UART0_RX_GPIO_IRQn);s_pin_irq_func[0] = func;break;
...
}//RX引脚将下降沿中断
void UART0_RX_GPIO_IRQHandler(void)
{// Check if the pin for UART0 is what triggered the RX PORT interruptif (PORT_GetPinIsf(UART0_RX_PORT_BASE, UART0_RX_GPIO_PIN_NUM) && s_pin_irq_func[0]){s_pin_irq_func[0](0);PORT_ClearPinsInterruptFlags(UART0_RX_PORT_BASE, ~0U);}
}
scuart_full_init //uart初始化进入 while 循环 检测有效的UART 波特率scuart_poll_for_activitybool scuart_poll_for_activity(const peripheral_descriptor_t *self)
{uint32_t baud;status_t autoBaudCompleted = autobaud_get_rate(self->instance, &baud);if (autoBaudCompleted == kStatus_Success){uart_config_t userConfig;UART_Type *base = get_uart_baseAddr(self->instance);UART_GetDefaultConfig(&userConfig);userConfig.baudRate_Bps = baud;userConfig.enableTx = true;userConfig.enableRx = true;if (UART_Init(base, &userConfig, get_uart_clock(self->instance)) == kStatus_Success){UART_SetSystemIRQ(self->instance, kPeripheralEnableIRQ);UART_EnableInterrupts(base, kUART_RxDataRegFullInterruptEnable);// Configure selected pin as uart peripheral interfaceself->pinmuxConfig(self->instance, kPinmuxType_Peripheral);// This was the byte pattern identified in autobaud detection, inform the command layers_scuart_byte_receive_callback(kFramingPacketStartByte);s_scuart_byte_receive_callback(kFramingPacketType_Ping);g_uartInitDone = true;return true;}else{autobaud_init(self->instance);}}return false;
}
波形
/** This function filters the invalid noises on LPUART rx pins by following characters:* For 0x5A, the interval between falling edges meets 3:3:2* For 0xA5, the interval between falling edges meets: 4:3* | 0x5A | 0xA6 |** ___ ___ _____ ___ ______ _____ ___ ________* | S 0 | 1 | 0 | 1 1 | 0 | 1 | 0 | STOP | S 0 | 1 1 | 0 0 | 1 | 0 | 1 STOP* ----- --- --- --- ----- ----- ---* ---------------------------------------------------------------------------* | 1st | 2nd | 3rd | | 1st | 2nd |* ---------------------------------------------------------------------------* | 3 : 3 : 2 | | 4 : 3 |
波特率计算思虑
計算波特率思路 :K64 bootloader 主频48MHZ, 要产生57600 bit/s 波特率,每传送一位需要833.33个时钟周期,取833;如果已知主频时钟和每一位的时钟周期,则可以计算出 波特率。
Bhost 采用UART 发0x5A 和 0xA6 两个字节给Bootloader,测出这两个字节共需要12598 个clock, 共传输15位,即每一位需要840clock;波特率为 48000000 / 840 = 57142. (取57600)。
令人疑惑的是15是怎么来的,对于0x5A ,起始位start 加上第一个bit位到这个字节的最后一个下降沿之间的 7 个bit,即8; 对于0xA6,我们有起始位start +6位到最后下降沿=7位。
status_t autobaud_get_rate(uint32_t instance, uint32_t *rate)
{if ((s_transitionCount == (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges)) &&(instance == s_instanceMeasured)){// Invalid bytes received.if (!is_falling_edge_interval_valid()){// Restart auto buad detectionautobaud_init(instance);return kStatus_Fail;}uint32_t calculatedBaud =(microseconds_get_clock() * (kNumberOfBitsForFirstByteMeasured + kNumberOfBitsForSecondByteMeasured)) /(uint32_t)(s_firstByteTotalTicks + s_secondByteTotalTicks);// Round the rate to the nearest step size// rounded = stepSize * (value/stepSize + .5)// multiplying by 10 since we can't work with floats// kAutobaudStepSize 为 1200,这个值是 57600 119200 38400 等常见波特率 公约数*rate = ((((calculatedBaud * 10) / kAutobaudStepSize) + 5) / 10) * kAutobaudStepSize;return kStatus_Success;}else{// no baud rate yet/inactivereturn kStatus_Fail;}
}
K64 计算 UART波特率相关推荐
- 【嵌入式】任意波特率的合理计算——高波特率、低误差
文章目录 一.概要 二.STM32F4波特率的计算方法 三.高波特率.低误差的计算方法 四.实验验证 1.与参考手册中的典型波特率误差进行比对 2.实际验证 一.概要 使用UART串口时往往比较喜欢配 ...
- NXP JN5169 UART 波特率设置
NXP JN5169 UART 波特率设置 一.系统时钟介绍 1.高速(32MHz)系统时钟 1.32MHz 晶体振荡器 2.高速RC振荡器 2.低速(32kHz)系统时钟 1.32 kHz RC 振 ...
- (100)Verilog HDL:UART波特率设计
(100)Verilog HDL:UART波特率设计 1.1 目录 1)目录 2)FPGA简介 3)Verilog HDL简介 4)Verilog HDL:UART波特率设计 5)结语 1.2 FPG ...
- NXP JN5169 UART波特率问题
被NXP JN5169的UART收数据大批量错误坑了一把,最后发现是NXP的速率计算因子误差太大导致. 写了个程序,把所有常见的波特率匹配了一把,匹配的结果(相对误差在千分之七以下)即波特率的计算因子 ...
- UART 波特率选择的认识与理解
笔者前几天碰到了串口波特率的问题,想要1M以上的波特率,发现波特率总是乱码,常用标准的几种波特率也不是很好用. 1.UART时钟情况说明 ch340G模块,时钟为12MHZ. 某PMC开发板,ARM ...
- TMS320F28335 uart波特率参数设置
结合自己调试的经验,这里做一个总结,uart的波特率参数需要通过计算来得到的,具体方法如下: void scic_echoback_init() {// Note: Clocks were turne ...
- (五)嵌入式:设置UART波特率并实现转变字符串大小,实现人机交互
本次实验使用开发板是美国Marvell公司生产的SOHO级网络通信微处理器芯片88E6218.开发环境是Ubuntu12.04,内核是UCLinux. 1.使用串口 本次课程主要是了解uart的使用, ...
- DSP:TMS320C6657 之 UART波特率问题
6657 设置串口波特率 以614400为例 (1)根据公式计算分频系数 (2)1GHz主频下 UART输入频率166666666Hz.(1/6) (3)16倍采样率下分频系数是16.95取整16,实 ...
- APB时钟计算串口波特率
与APB计算定时器频率相似 同样在datasheet中查找串口使用的总线 STM32串口波特率通过USART_BRR进行设置 可以看到USART1挂在APB2,APB2总线的速率是84MHz 可以使用 ...
- 嵌入式 - 晶振频率的来源和UART波特率的选择
电路板上经常要用到32.768KHz的晶振,表示晶振经过32768K个周期就是1s,16进制就是0x8000,是2的n次方形式,2^15. 这颗料已经出现了20年,非常普遍,也非常便宜,在各种电路中使 ...
最新文章
- win7mysql免安装版安装_win7下MySQL免安装版下载安装、配置与使用
- 小 Q 与函数求和 1(牛客练习赛 81 E)
- 【转】ABP源码分析二十三:Authorization
- 合肥注册公司(各区注册地点说明)
- linux 分配组命令,linux下一个用户如何分配给多个用户组?求命令,谢了。
- ajax常见的面试题
- echarts源码打包_Echarts源码阅读指南
- [10秒学会] - iOS录制屏幕 ReplayKit
- 解决响应式布局border带来的麻烦
- spring视频教程
- odoo stock库存模块
- mp c2011sp文件服务器,理光Ricoh MP C2011SP驱动
- hitb2017 sentosa writeup
- 第50篇-企查查请求头参数分析【2022-09-29】
- ESR-CMDS参数含义
- 排序算法系列之(二)——冒泡排序名字最为形象的一个
- 小白如何学3D建模?从零开始变大神
- 总结 离散数学知识点
- TCP四次挥手断开连接
- Halcon图像预处理-感兴趣区域(ROI)